@gurulu/cli 1.2.2 → 1.3.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/dist/bin.js +146 -50
- package/dist/index.js +146 -50
- package/dist/lib/detect.d.ts +5 -0
- package/dist/lib/detect.d.ts.map +1 -1
- package/dist/lib/detect.js +22 -1
- package/dist/wizard/features.d.ts +28 -0
- package/dist/wizard/features.d.ts.map +1 -0
- package/dist/wizard/run.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -25118,7 +25118,7 @@ function sleep(ms) {
|
|
|
25118
25118
|
// src/wizard/run.ts
|
|
25119
25119
|
import { existsSync as existsSync9, mkdirSync as mkdirSync2, writeFileSync as writeFileSync8 } from "node:fs";
|
|
25120
25120
|
import { dirname as dirname3 } from "node:path";
|
|
25121
|
-
import * as
|
|
25121
|
+
import * as p4 from "@clack/prompts";
|
|
25122
25122
|
|
|
25123
25123
|
// src/commands/pull.ts
|
|
25124
25124
|
import { writeFileSync as writeFileSync3 } from "node:fs";
|
|
@@ -25262,6 +25262,17 @@ var pullCmd = defineCommand({
|
|
|
25262
25262
|
// src/lib/detect.ts
|
|
25263
25263
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
25264
25264
|
import { dirname as dirname2, join as join5, parse } from "node:path";
|
|
25265
|
+
var LLM_DEP_MAP = {
|
|
25266
|
+
openai: "openai",
|
|
25267
|
+
"@anthropic-ai/sdk": "anthropic",
|
|
25268
|
+
"@langchain/core": "langchain",
|
|
25269
|
+
langchain: "langchain",
|
|
25270
|
+
"@google/generative-ai": "google-genai",
|
|
25271
|
+
ai: "vercel-ai",
|
|
25272
|
+
"cohere-ai": "cohere",
|
|
25273
|
+
"@mistralai/mistralai": "mistral",
|
|
25274
|
+
ollama: "ollama"
|
|
25275
|
+
};
|
|
25265
25276
|
function readPackageJson(dir) {
|
|
25266
25277
|
const p = join5(dir, "package.json");
|
|
25267
25278
|
if (!existsSync4(p))
|
|
@@ -25347,6 +25358,14 @@ function frameworkRuntime(fw) {
|
|
|
25347
25358
|
return "unknown";
|
|
25348
25359
|
}
|
|
25349
25360
|
}
|
|
25361
|
+
function detectLlmFrameworks(pkg) {
|
|
25362
|
+
const found = new Set;
|
|
25363
|
+
for (const [dep, fw] of Object.entries(LLM_DEP_MAP)) {
|
|
25364
|
+
if (hasDep(pkg, dep))
|
|
25365
|
+
found.add(fw);
|
|
25366
|
+
}
|
|
25367
|
+
return [...found];
|
|
25368
|
+
}
|
|
25350
25369
|
function detectProject(dir) {
|
|
25351
25370
|
const pkg = readPackageJson(dir);
|
|
25352
25371
|
const framework = detectFramework(pkg, dir);
|
|
@@ -25356,7 +25375,8 @@ function detectProject(dir) {
|
|
|
25356
25375
|
framework,
|
|
25357
25376
|
runtime: frameworkRuntime(framework),
|
|
25358
25377
|
packageManager: detectPackageManager(dir),
|
|
25359
|
-
packageJson: pkg
|
|
25378
|
+
packageJson: pkg,
|
|
25379
|
+
llmFrameworks: detectLlmFrameworks(pkg)
|
|
25360
25380
|
};
|
|
25361
25381
|
}
|
|
25362
25382
|
|
|
@@ -26133,8 +26153,77 @@ function gatherContext(opts) {
|
|
|
26133
26153
|
return { files, capped, totalBytes };
|
|
26134
26154
|
}
|
|
26135
26155
|
|
|
26136
|
-
// src/wizard/
|
|
26156
|
+
// src/wizard/features.ts
|
|
26137
26157
|
import * as p2 from "@clack/prompts";
|
|
26158
|
+
function availableFeatures(detected) {
|
|
26159
|
+
const isBrowser = frameworkRuntime(detected.framework) !== "node";
|
|
26160
|
+
const feats = [];
|
|
26161
|
+
feats.push({
|
|
26162
|
+
key: "error",
|
|
26163
|
+
label: "Hata takibi",
|
|
26164
|
+
detail: "Tarayıcı JS hatalarını otomatik yakala (js_error)",
|
|
26165
|
+
enableHint: isBrowser ? "gurulu.init({ ..., autocapture: { js_error: true } })" : "Sunucu hatalarında: gurulu.track('js_error', { message, error_type })",
|
|
26166
|
+
recommended: isBrowser
|
|
26167
|
+
});
|
|
26168
|
+
if (detected.llmFrameworks.length > 0) {
|
|
26169
|
+
feats.push({
|
|
26170
|
+
key: "llm",
|
|
26171
|
+
label: `LLM analizi (${detected.llmFrameworks.join(", ")} tespit edildi)`,
|
|
26172
|
+
detail: "AI çağrı maliyeti/latency/hata/model performansı",
|
|
26173
|
+
enableHint: "import { wrapOpenAI } from '@gurulu/node'; const client = wrapOpenAI(openai);",
|
|
26174
|
+
recommended: true
|
|
26175
|
+
});
|
|
26176
|
+
}
|
|
26177
|
+
if (isBrowser) {
|
|
26178
|
+
feats.push({
|
|
26179
|
+
key: "activation",
|
|
26180
|
+
label: "Activation (popup · tur · A/B test · kişiselleştirme)",
|
|
26181
|
+
detail: "Dashboard'dan yayınla, SDK render etsin (Action Layer)",
|
|
26182
|
+
enableHint: "import { runActivation } from '@gurulu/web/activate'; runActivation(gurulu);",
|
|
26183
|
+
recommended: false
|
|
26184
|
+
});
|
|
26185
|
+
}
|
|
26186
|
+
return feats;
|
|
26187
|
+
}
|
|
26188
|
+
async function runFeatures(client, detected, opts) {
|
|
26189
|
+
const avail = availableFeatures(detected);
|
|
26190
|
+
if (avail.length === 0 || !opts.authed)
|
|
26191
|
+
return { selected: [], registered: false };
|
|
26192
|
+
let selectedKeys;
|
|
26193
|
+
if (opts.yes) {
|
|
26194
|
+
selectedKeys = avail.filter((f3) => f3.recommended).map((f3) => f3.key);
|
|
26195
|
+
} else {
|
|
26196
|
+
const choice = await p2.multiselect({
|
|
26197
|
+
message: "Hangi özellikleri kuralım? (event'ler registry'ye otomatik eklenir)",
|
|
26198
|
+
options: avail.map((f3) => ({ value: f3.key, label: f3.label, hint: f3.detail })),
|
|
26199
|
+
initialValues: avail.filter((f3) => f3.recommended).map((f3) => f3.key),
|
|
26200
|
+
required: false
|
|
26201
|
+
});
|
|
26202
|
+
if (p2.isCancel(choice))
|
|
26203
|
+
return { selected: [], registered: false };
|
|
26204
|
+
selectedKeys = choice;
|
|
26205
|
+
}
|
|
26206
|
+
if (selectedKeys.length === 0)
|
|
26207
|
+
return { selected: [], registered: false };
|
|
26208
|
+
const selected = avail.filter((f3) => selectedKeys.includes(f3.key));
|
|
26209
|
+
const s2 = p2.spinner();
|
|
26210
|
+
s2.start("Özellikler registry'ye kuruluyor…");
|
|
26211
|
+
try {
|
|
26212
|
+
await client.post("/features/register", { features: selectedKeys });
|
|
26213
|
+
s2.stop(c3.neon(`✓ ${selected.length} özellik kuruldu`));
|
|
26214
|
+
} catch {
|
|
26215
|
+
s2.stop("Özellik kurulumu atlandı (gateway hatası) — sonra: gurulu doctor", 1);
|
|
26216
|
+
return { selected, registered: false };
|
|
26217
|
+
}
|
|
26218
|
+
p2.note(selected.map((f3) => `${c3.bold(f3.label)}
|
|
26219
|
+
${c3.dim(f3.enableHint)}`).join(`
|
|
26220
|
+
|
|
26221
|
+
`), "Etkinleştirme");
|
|
26222
|
+
return { selected, registered: true };
|
|
26223
|
+
}
|
|
26224
|
+
|
|
26225
|
+
// src/wizard/plan.ts
|
|
26226
|
+
import * as p3 from "@clack/prompts";
|
|
26138
26227
|
async function fetchPlan(client, context, input) {
|
|
26139
26228
|
if (context.files.length === 0)
|
|
26140
26229
|
return null;
|
|
@@ -26179,12 +26268,12 @@ function formatPlan(plan) {
|
|
|
26179
26268
|
`).trimEnd();
|
|
26180
26269
|
}
|
|
26181
26270
|
async function renderPlan(plan) {
|
|
26182
|
-
|
|
26271
|
+
p3.note(formatPlan(plan), plan.summary);
|
|
26183
26272
|
const newCount = plan.events.filter((e2) => !e2.existing).length;
|
|
26184
|
-
const ok = await
|
|
26273
|
+
const ok = await p3.confirm({
|
|
26185
26274
|
message: `${plan.events.length} event (${newCount} yeni) — bu planı uygula?`
|
|
26186
26275
|
});
|
|
26187
|
-
if (
|
|
26276
|
+
if (p3.isCancel(ok) || !ok)
|
|
26188
26277
|
return null;
|
|
26189
26278
|
return plan.events;
|
|
26190
26279
|
}
|
|
@@ -26199,8 +26288,8 @@ import { promisify } from "node:util";
|
|
|
26199
26288
|
|
|
26200
26289
|
// src/wizard/guard.ts
|
|
26201
26290
|
import { basename, isAbsolute, relative as relative2, resolve } from "node:path";
|
|
26202
|
-
function resolveInCwd(
|
|
26203
|
-
return isAbsolute(
|
|
26291
|
+
function resolveInCwd(p4, cwd) {
|
|
26292
|
+
return isAbsolute(p4) ? p4 : resolve(cwd, p4);
|
|
26204
26293
|
}
|
|
26205
26294
|
function isAdditiveEdit(find, replace) {
|
|
26206
26295
|
if (find.length === 0)
|
|
@@ -26277,8 +26366,8 @@ function isAllowedBash(cmd) {
|
|
|
26277
26366
|
}
|
|
26278
26367
|
return { ok: false, reason: `allowlist dışı binary: ${bin}` };
|
|
26279
26368
|
}
|
|
26280
|
-
function isAllowedPath(
|
|
26281
|
-
const abs = isAbsolute(
|
|
26369
|
+
function isAllowedPath(p4, cwd) {
|
|
26370
|
+
const abs = isAbsolute(p4) ? p4 : resolve(cwd, p4);
|
|
26282
26371
|
const rel = relative2(cwd, abs);
|
|
26283
26372
|
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
26284
26373
|
return { ok: false, reason: "cwd dışı yol" };
|
|
@@ -26542,16 +26631,16 @@ var FRAMEWORKS = [
|
|
|
26542
26631
|
"node-server"
|
|
26543
26632
|
];
|
|
26544
26633
|
function bail() {
|
|
26545
|
-
|
|
26634
|
+
p4.cancel("İptal edildi.");
|
|
26546
26635
|
process.exit(0);
|
|
26547
26636
|
}
|
|
26548
26637
|
async function runWizard(opts) {
|
|
26549
26638
|
if (process.stdout.isTTY)
|
|
26550
26639
|
process.stdout.write(banner());
|
|
26551
|
-
|
|
26640
|
+
p4.intro(c3.dim("otonom kurulum başlıyor — auth → workspace → install → wire"));
|
|
26552
26641
|
const TOTAL = 6;
|
|
26553
26642
|
const phase = (n2, label) => {
|
|
26554
|
-
|
|
26643
|
+
p4.log.step(`${c3.dim(`[${n2}/${TOTAL}]`)} ${c3.bold(label)}`);
|
|
26555
26644
|
};
|
|
26556
26645
|
phase(1, "Kimlik doğrulama");
|
|
26557
26646
|
const auth = await ensureAuth({
|
|
@@ -26568,18 +26657,18 @@ async function runWizard(opts) {
|
|
|
26568
26657
|
if (opts.framework && FRAMEWORKS.includes(opts.framework)) {
|
|
26569
26658
|
framework = opts.framework;
|
|
26570
26659
|
} else if (!opts.yes) {
|
|
26571
|
-
const ok = await
|
|
26660
|
+
const ok = await p4.confirm({
|
|
26572
26661
|
message: `Saptanan: ${detected.framework} (${detected.packageManager}). Doğru mu?`
|
|
26573
26662
|
});
|
|
26574
|
-
if (
|
|
26663
|
+
if (p4.isCancel(ok))
|
|
26575
26664
|
bail();
|
|
26576
26665
|
if (!ok) {
|
|
26577
|
-
const choice = await
|
|
26666
|
+
const choice = await p4.select({
|
|
26578
26667
|
message: "Framework seç",
|
|
26579
26668
|
options: FRAMEWORKS.map((f3) => ({ value: f3, label: f3 })),
|
|
26580
26669
|
initialValue: detected.framework
|
|
26581
26670
|
});
|
|
26582
|
-
if (
|
|
26671
|
+
if (p4.isCancel(choice))
|
|
26583
26672
|
bail();
|
|
26584
26673
|
framework = choice;
|
|
26585
26674
|
}
|
|
@@ -26599,17 +26688,21 @@ async function runWizard(opts) {
|
|
|
26599
26688
|
if (approved)
|
|
26600
26689
|
approvedEvents = approved;
|
|
26601
26690
|
} else {
|
|
26602
|
-
|
|
26691
|
+
p4.log.info("AI planı yok — autocapture + sektör paketi (deterministik floor).");
|
|
26603
26692
|
}
|
|
26604
26693
|
}
|
|
26694
|
+
let featuresResult = { selected: [], registered: false };
|
|
26695
|
+
if (authed) {
|
|
26696
|
+
featuresResult = await runFeatures(client, project, { yes: opts.yes, authed });
|
|
26697
|
+
}
|
|
26605
26698
|
phase(4, "SDK kurulumu");
|
|
26606
26699
|
let installed = false;
|
|
26607
26700
|
if (opts.noInstall) {
|
|
26608
|
-
|
|
26701
|
+
p4.log.info(`SDK kurulumu atlandı — elle: ${plan.installCommand}`);
|
|
26609
26702
|
} else if (!detected.hasPackageJson) {
|
|
26610
|
-
|
|
26703
|
+
p4.log.warn("package.json yok — script tag ile kur: https://cdn.gurulu.io/t.js");
|
|
26611
26704
|
} else {
|
|
26612
|
-
const s2 =
|
|
26705
|
+
const s2 = p4.spinner();
|
|
26613
26706
|
s2.start(`${plan.sdk} kuruluyor (${plan.installCommand})…`);
|
|
26614
26707
|
const res = await execInstall(plan, { cwd: opts.cwd });
|
|
26615
26708
|
if (res.ok) {
|
|
@@ -26636,7 +26729,7 @@ async function runWizard(opts) {
|
|
|
26636
26729
|
if (auth.apiKey.startsWith("sk_")) {
|
|
26637
26730
|
vars.push({ key: k2.key, value: auth.apiKey });
|
|
26638
26731
|
} else {
|
|
26639
|
-
|
|
26732
|
+
p4.log.warn("GURULU_SECRET_KEY atlandı (login token workspace sk_ anahtarı değil). Dashboard → Settings → API Keys'ten server key oluşturup .env'e elle ekle.");
|
|
26640
26733
|
}
|
|
26641
26734
|
}
|
|
26642
26735
|
}
|
|
@@ -26656,7 +26749,7 @@ async function runWizard(opts) {
|
|
|
26656
26749
|
}
|
|
26657
26750
|
let registeredCount = 0;
|
|
26658
26751
|
if (approvedEvents.length > 0) {
|
|
26659
|
-
const s2 =
|
|
26752
|
+
const s2 = p4.spinner();
|
|
26660
26753
|
s2.start("Yeni eventler registry kuyruguna oneriliyor…");
|
|
26661
26754
|
const res = await registerNewEvents(client, approvedEvents);
|
|
26662
26755
|
registeredCount = res.registered.length;
|
|
@@ -26665,29 +26758,29 @@ async function runWizard(opts) {
|
|
|
26665
26758
|
let wiredCount = 0;
|
|
26666
26759
|
if (approvedEvents.length > 0) {
|
|
26667
26760
|
if (opts.noAi) {
|
|
26668
|
-
|
|
26761
|
+
p4.log.message(`Capture — şu çağrıları ekle:
|
|
26669
26762
|
${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
26670
26763
|
} else {
|
|
26671
26764
|
const wireFiles = gatherContext({ cwd: opts.cwd }).files.map((f3) => f3.path);
|
|
26672
26765
|
const snapshots = new Map;
|
|
26673
|
-
const s2 =
|
|
26766
|
+
const s2 = p4.spinner();
|
|
26674
26767
|
s2.start("AI capture wiring (kod düzenleniyor)…");
|
|
26675
26768
|
const outcome = await runWireAgent(client, { cwd: opts.cwd, events: approvedEvents, identifyHint, files: wireFiles }, snapshots);
|
|
26676
26769
|
s2.stop(`wire: ${outcome.changedFiles.length} dosya / ${outcome.steps} adım (${outcome.stoppedReason})`);
|
|
26677
26770
|
if (outcome.changedFiles.length > 0) {
|
|
26678
|
-
|
|
26679
|
-
const keep = opts.yes ? true : await
|
|
26771
|
+
p4.log.message(formatWireDiff(opts.cwd, snapshots));
|
|
26772
|
+
const keep = opts.yes ? true : await p4.confirm({
|
|
26680
26773
|
message: `${outcome.changedFiles.length} dosyadaki wire değişikliklerini tut?`
|
|
26681
26774
|
});
|
|
26682
|
-
if (
|
|
26775
|
+
if (p4.isCancel(keep) || !keep) {
|
|
26683
26776
|
restoreSnapshots(opts.cwd, snapshots);
|
|
26684
|
-
|
|
26685
|
-
|
|
26777
|
+
p4.log.info("Wire geri alındı — capture snippet rehberi:");
|
|
26778
|
+
p4.log.message(captureGuide(approvedEvents, identifyHint, isNode));
|
|
26686
26779
|
} else {
|
|
26687
26780
|
wiredCount = outcome.changedFiles.length;
|
|
26688
26781
|
}
|
|
26689
26782
|
} else {
|
|
26690
|
-
|
|
26783
|
+
p4.log.message(`Capture (AI gömemedi → snippet-göster) — şu çağrıları ekle:
|
|
26691
26784
|
${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
26692
26785
|
}
|
|
26693
26786
|
}
|
|
@@ -26706,15 +26799,18 @@ ${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
|
26706
26799
|
if (wiredCount > 0)
|
|
26707
26800
|
lines.push(`✓ ${wiredCount} dosya AI ile capture wire edildi`);
|
|
26708
26801
|
}
|
|
26802
|
+
if (featuresResult.registered && featuresResult.selected.length > 0) {
|
|
26803
|
+
lines.push(`✓ özellikler: ${featuresResult.selected.map((f3) => f3.key).join(", ")} kuruldu`);
|
|
26804
|
+
}
|
|
26709
26805
|
lines.push(`✓ .gurulu/config.json${pulled ? " + registry pull" : ""}`);
|
|
26710
|
-
|
|
26806
|
+
p4.note(lines.join(`
|
|
26711
26807
|
`), c3.neon("✦ Değişiklikler"));
|
|
26712
26808
|
if (inj.strategy !== "prepend-entry" || inj.reason === "no-entry") {
|
|
26713
|
-
|
|
26809
|
+
p4.log.info(`Wire: ${inj.wireHint ?? plan.placementHint}`);
|
|
26714
26810
|
if (inj.strategy === "manual")
|
|
26715
|
-
|
|
26811
|
+
p4.log.message(plan.initSnippet);
|
|
26716
26812
|
}
|
|
26717
|
-
|
|
26813
|
+
p4.outro(`${c3.neon("\uD83E\uDD89 Hazır!")} ${c3.dim("Doğrula:")} ${c3.bold("gurulu doctor")} ${c3.dim("·")} ${c3.dim("Dashboard:")} ${c3.cyan("https://dashboard.gurulu.io/app?onboard=done")}`);
|
|
26718
26814
|
}
|
|
26719
26815
|
async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
26720
26816
|
if (opts.writeKey) {
|
|
@@ -26737,7 +26833,7 @@ async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
|
26737
26833
|
selected = CREATE;
|
|
26738
26834
|
} else {
|
|
26739
26835
|
const initial = list.find((w2) => w2.workspace_id === authWorkspaceId)?.workspace_id ?? list[0]?.workspace_id ?? CREATE;
|
|
26740
|
-
const choice = await
|
|
26836
|
+
const choice = await p4.select({
|
|
26741
26837
|
message: "Workspace seç",
|
|
26742
26838
|
options: [
|
|
26743
26839
|
...list.map((w2) => ({ value: w2.workspace_id, label: w2.name, hint: w2.slug })),
|
|
@@ -26745,26 +26841,26 @@ async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
|
26745
26841
|
],
|
|
26746
26842
|
initialValue: initial
|
|
26747
26843
|
});
|
|
26748
|
-
if (
|
|
26844
|
+
if (p4.isCancel(choice))
|
|
26749
26845
|
bail();
|
|
26750
26846
|
selected = choice;
|
|
26751
26847
|
}
|
|
26752
26848
|
if (selected === CREATE) {
|
|
26753
|
-
const name = await
|
|
26849
|
+
const name = await p4.text({
|
|
26754
26850
|
message: "Workspace adı",
|
|
26755
26851
|
placeholder: "My App",
|
|
26756
26852
|
validate: (v2) => v2.trim() ? undefined : "gerekli"
|
|
26757
26853
|
});
|
|
26758
|
-
if (
|
|
26854
|
+
if (p4.isCancel(name))
|
|
26759
26855
|
bail();
|
|
26760
|
-
const domain = await
|
|
26856
|
+
const domain = await p4.text({
|
|
26761
26857
|
message: "Domain",
|
|
26762
26858
|
placeholder: "example.com",
|
|
26763
26859
|
validate: (v2) => v2.trim().length >= 3 ? undefined : "geçerli domain gerekli"
|
|
26764
26860
|
});
|
|
26765
|
-
if (
|
|
26861
|
+
if (p4.isCancel(domain))
|
|
26766
26862
|
bail();
|
|
26767
|
-
const s2 =
|
|
26863
|
+
const s2 = p4.spinner();
|
|
26768
26864
|
s2.start("Workspace oluşturuluyor…");
|
|
26769
26865
|
const created = await client.createWorkspace({
|
|
26770
26866
|
name: String(name).trim(),
|
|
@@ -27089,7 +27185,7 @@ import { execFile as execFile2 } from "node:child_process";
|
|
|
27089
27185
|
import { existsSync as existsSync11, readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync10 } from "node:fs";
|
|
27090
27186
|
import { join as join10 } from "node:path";
|
|
27091
27187
|
import { promisify as promisify2 } from "node:util";
|
|
27092
|
-
import * as
|
|
27188
|
+
import * as p5 from "@clack/prompts";
|
|
27093
27189
|
var pexec2 = promisify2(execFile2);
|
|
27094
27190
|
var ENV_FILES = [".env.local", ".env"];
|
|
27095
27191
|
var GURULU_PREFIXES = ["GURULU_", "NEXT_PUBLIC_GURULU", "VITE_GURULU"];
|
|
@@ -27116,23 +27212,23 @@ var uninstallCmd = defineCommand({
|
|
|
27116
27212
|
const config = readProjectConfig(cwd);
|
|
27117
27213
|
const detected = detectProject(cwd);
|
|
27118
27214
|
const pkg = config?.sdk_preference === "node" ? "@gurulu/node" : "@gurulu/web";
|
|
27119
|
-
|
|
27120
|
-
|
|
27215
|
+
p5.intro("Gurulu uninstall");
|
|
27216
|
+
p5.note([
|
|
27121
27217
|
`• SDK kaldır: ${pkg} (${detected.packageManager})`,
|
|
27122
27218
|
`• env temizle: ${ENV_FILES.join(", ")} (GURULU_* anahtarları)`,
|
|
27123
27219
|
"• .gurulu/ dizinini sil"
|
|
27124
27220
|
].join(`
|
|
27125
27221
|
`), "Şunlar yapılacak");
|
|
27126
27222
|
if (!args.yes) {
|
|
27127
|
-
const ok = await
|
|
27128
|
-
if (
|
|
27129
|
-
|
|
27223
|
+
const ok = await p5.confirm({ message: "Devam edilsin mi?" });
|
|
27224
|
+
if (p5.isCancel(ok) || !ok) {
|
|
27225
|
+
p5.cancel("İptal.");
|
|
27130
27226
|
process.exit(0);
|
|
27131
27227
|
}
|
|
27132
27228
|
}
|
|
27133
27229
|
if (!args["no-deps"] && detected.hasPackageJson) {
|
|
27134
27230
|
const { bin, args: a2 } = removeCmd(detected.packageManager, pkg);
|
|
27135
|
-
const s2 =
|
|
27231
|
+
const s2 = p5.spinner();
|
|
27136
27232
|
s2.start(`${pkg} kaldırılıyor…`);
|
|
27137
27233
|
try {
|
|
27138
27234
|
await pexec2(bin, a2, { cwd, timeout: 120000 });
|
|
@@ -27155,7 +27251,7 @@ var uninstallCmd = defineCommand({
|
|
|
27155
27251
|
const guruluDir = join10(cwd, ".gurulu");
|
|
27156
27252
|
if (existsSync11(guruluDir))
|
|
27157
27253
|
rmSync(guruluDir, { recursive: true, force: true });
|
|
27158
|
-
|
|
27254
|
+
p5.outro(`Kaldırıldı. env: ${cleaned.join(", ") || "değişiklik yok"} · .gurulu silindi. (Koddaki init/track çağrılarını elle çıkar.)`);
|
|
27159
27255
|
}
|
|
27160
27256
|
});
|
|
27161
27257
|
|
package/dist/index.js
CHANGED
|
@@ -24695,7 +24695,7 @@ function sleep(ms) {
|
|
|
24695
24695
|
// src/wizard/run.ts
|
|
24696
24696
|
import { existsSync as existsSync9, mkdirSync as mkdirSync2, writeFileSync as writeFileSync8 } from "node:fs";
|
|
24697
24697
|
import { dirname as dirname3 } from "node:path";
|
|
24698
|
-
import * as
|
|
24698
|
+
import * as p4 from "@clack/prompts";
|
|
24699
24699
|
|
|
24700
24700
|
// src/commands/pull.ts
|
|
24701
24701
|
import { writeFileSync as writeFileSync3 } from "node:fs";
|
|
@@ -24839,6 +24839,17 @@ var pullCmd = defineCommand({
|
|
|
24839
24839
|
// src/lib/detect.ts
|
|
24840
24840
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
24841
24841
|
import { dirname as dirname2, join as join5, parse } from "node:path";
|
|
24842
|
+
var LLM_DEP_MAP = {
|
|
24843
|
+
openai: "openai",
|
|
24844
|
+
"@anthropic-ai/sdk": "anthropic",
|
|
24845
|
+
"@langchain/core": "langchain",
|
|
24846
|
+
langchain: "langchain",
|
|
24847
|
+
"@google/generative-ai": "google-genai",
|
|
24848
|
+
ai: "vercel-ai",
|
|
24849
|
+
"cohere-ai": "cohere",
|
|
24850
|
+
"@mistralai/mistralai": "mistral",
|
|
24851
|
+
ollama: "ollama"
|
|
24852
|
+
};
|
|
24842
24853
|
function readPackageJson(dir) {
|
|
24843
24854
|
const p = join5(dir, "package.json");
|
|
24844
24855
|
if (!existsSync4(p))
|
|
@@ -24924,6 +24935,14 @@ function frameworkRuntime(fw) {
|
|
|
24924
24935
|
return "unknown";
|
|
24925
24936
|
}
|
|
24926
24937
|
}
|
|
24938
|
+
function detectLlmFrameworks(pkg) {
|
|
24939
|
+
const found = new Set;
|
|
24940
|
+
for (const [dep, fw] of Object.entries(LLM_DEP_MAP)) {
|
|
24941
|
+
if (hasDep(pkg, dep))
|
|
24942
|
+
found.add(fw);
|
|
24943
|
+
}
|
|
24944
|
+
return [...found];
|
|
24945
|
+
}
|
|
24927
24946
|
function detectProject(dir) {
|
|
24928
24947
|
const pkg = readPackageJson(dir);
|
|
24929
24948
|
const framework = detectFramework(pkg, dir);
|
|
@@ -24933,7 +24952,8 @@ function detectProject(dir) {
|
|
|
24933
24952
|
framework,
|
|
24934
24953
|
runtime: frameworkRuntime(framework),
|
|
24935
24954
|
packageManager: detectPackageManager(dir),
|
|
24936
|
-
packageJson: pkg
|
|
24955
|
+
packageJson: pkg,
|
|
24956
|
+
llmFrameworks: detectLlmFrameworks(pkg)
|
|
24937
24957
|
};
|
|
24938
24958
|
}
|
|
24939
24959
|
|
|
@@ -25710,8 +25730,77 @@ function gatherContext(opts) {
|
|
|
25710
25730
|
return { files, capped, totalBytes };
|
|
25711
25731
|
}
|
|
25712
25732
|
|
|
25713
|
-
// src/wizard/
|
|
25733
|
+
// src/wizard/features.ts
|
|
25714
25734
|
import * as p2 from "@clack/prompts";
|
|
25735
|
+
function availableFeatures(detected) {
|
|
25736
|
+
const isBrowser = frameworkRuntime(detected.framework) !== "node";
|
|
25737
|
+
const feats = [];
|
|
25738
|
+
feats.push({
|
|
25739
|
+
key: "error",
|
|
25740
|
+
label: "Hata takibi",
|
|
25741
|
+
detail: "Tarayıcı JS hatalarını otomatik yakala (js_error)",
|
|
25742
|
+
enableHint: isBrowser ? "gurulu.init({ ..., autocapture: { js_error: true } })" : "Sunucu hatalarında: gurulu.track('js_error', { message, error_type })",
|
|
25743
|
+
recommended: isBrowser
|
|
25744
|
+
});
|
|
25745
|
+
if (detected.llmFrameworks.length > 0) {
|
|
25746
|
+
feats.push({
|
|
25747
|
+
key: "llm",
|
|
25748
|
+
label: `LLM analizi (${detected.llmFrameworks.join(", ")} tespit edildi)`,
|
|
25749
|
+
detail: "AI çağrı maliyeti/latency/hata/model performansı",
|
|
25750
|
+
enableHint: "import { wrapOpenAI } from '@gurulu/node'; const client = wrapOpenAI(openai);",
|
|
25751
|
+
recommended: true
|
|
25752
|
+
});
|
|
25753
|
+
}
|
|
25754
|
+
if (isBrowser) {
|
|
25755
|
+
feats.push({
|
|
25756
|
+
key: "activation",
|
|
25757
|
+
label: "Activation (popup · tur · A/B test · kişiselleştirme)",
|
|
25758
|
+
detail: "Dashboard'dan yayınla, SDK render etsin (Action Layer)",
|
|
25759
|
+
enableHint: "import { runActivation } from '@gurulu/web/activate'; runActivation(gurulu);",
|
|
25760
|
+
recommended: false
|
|
25761
|
+
});
|
|
25762
|
+
}
|
|
25763
|
+
return feats;
|
|
25764
|
+
}
|
|
25765
|
+
async function runFeatures(client, detected, opts) {
|
|
25766
|
+
const avail = availableFeatures(detected);
|
|
25767
|
+
if (avail.length === 0 || !opts.authed)
|
|
25768
|
+
return { selected: [], registered: false };
|
|
25769
|
+
let selectedKeys;
|
|
25770
|
+
if (opts.yes) {
|
|
25771
|
+
selectedKeys = avail.filter((f3) => f3.recommended).map((f3) => f3.key);
|
|
25772
|
+
} else {
|
|
25773
|
+
const choice = await p2.multiselect({
|
|
25774
|
+
message: "Hangi özellikleri kuralım? (event'ler registry'ye otomatik eklenir)",
|
|
25775
|
+
options: avail.map((f3) => ({ value: f3.key, label: f3.label, hint: f3.detail })),
|
|
25776
|
+
initialValues: avail.filter((f3) => f3.recommended).map((f3) => f3.key),
|
|
25777
|
+
required: false
|
|
25778
|
+
});
|
|
25779
|
+
if (p2.isCancel(choice))
|
|
25780
|
+
return { selected: [], registered: false };
|
|
25781
|
+
selectedKeys = choice;
|
|
25782
|
+
}
|
|
25783
|
+
if (selectedKeys.length === 0)
|
|
25784
|
+
return { selected: [], registered: false };
|
|
25785
|
+
const selected = avail.filter((f3) => selectedKeys.includes(f3.key));
|
|
25786
|
+
const s2 = p2.spinner();
|
|
25787
|
+
s2.start("Özellikler registry'ye kuruluyor…");
|
|
25788
|
+
try {
|
|
25789
|
+
await client.post("/features/register", { features: selectedKeys });
|
|
25790
|
+
s2.stop(c3.neon(`✓ ${selected.length} özellik kuruldu`));
|
|
25791
|
+
} catch {
|
|
25792
|
+
s2.stop("Özellik kurulumu atlandı (gateway hatası) — sonra: gurulu doctor", 1);
|
|
25793
|
+
return { selected, registered: false };
|
|
25794
|
+
}
|
|
25795
|
+
p2.note(selected.map((f3) => `${c3.bold(f3.label)}
|
|
25796
|
+
${c3.dim(f3.enableHint)}`).join(`
|
|
25797
|
+
|
|
25798
|
+
`), "Etkinleştirme");
|
|
25799
|
+
return { selected, registered: true };
|
|
25800
|
+
}
|
|
25801
|
+
|
|
25802
|
+
// src/wizard/plan.ts
|
|
25803
|
+
import * as p3 from "@clack/prompts";
|
|
25715
25804
|
async function fetchPlan(client, context, input) {
|
|
25716
25805
|
if (context.files.length === 0)
|
|
25717
25806
|
return null;
|
|
@@ -25756,12 +25845,12 @@ function formatPlan(plan) {
|
|
|
25756
25845
|
`).trimEnd();
|
|
25757
25846
|
}
|
|
25758
25847
|
async function renderPlan(plan) {
|
|
25759
|
-
|
|
25848
|
+
p3.note(formatPlan(plan), plan.summary);
|
|
25760
25849
|
const newCount = plan.events.filter((e2) => !e2.existing).length;
|
|
25761
|
-
const ok = await
|
|
25850
|
+
const ok = await p3.confirm({
|
|
25762
25851
|
message: `${plan.events.length} event (${newCount} yeni) — bu planı uygula?`
|
|
25763
25852
|
});
|
|
25764
|
-
if (
|
|
25853
|
+
if (p3.isCancel(ok) || !ok)
|
|
25765
25854
|
return null;
|
|
25766
25855
|
return plan.events;
|
|
25767
25856
|
}
|
|
@@ -25776,8 +25865,8 @@ import { promisify } from "node:util";
|
|
|
25776
25865
|
|
|
25777
25866
|
// src/wizard/guard.ts
|
|
25778
25867
|
import { basename, isAbsolute, relative as relative2, resolve } from "node:path";
|
|
25779
|
-
function resolveInCwd(
|
|
25780
|
-
return isAbsolute(
|
|
25868
|
+
function resolveInCwd(p4, cwd) {
|
|
25869
|
+
return isAbsolute(p4) ? p4 : resolve(cwd, p4);
|
|
25781
25870
|
}
|
|
25782
25871
|
function isAdditiveEdit(find, replace) {
|
|
25783
25872
|
if (find.length === 0)
|
|
@@ -25854,8 +25943,8 @@ function isAllowedBash(cmd) {
|
|
|
25854
25943
|
}
|
|
25855
25944
|
return { ok: false, reason: `allowlist dışı binary: ${bin}` };
|
|
25856
25945
|
}
|
|
25857
|
-
function isAllowedPath(
|
|
25858
|
-
const abs = isAbsolute(
|
|
25946
|
+
function isAllowedPath(p4, cwd) {
|
|
25947
|
+
const abs = isAbsolute(p4) ? p4 : resolve(cwd, p4);
|
|
25859
25948
|
const rel = relative2(cwd, abs);
|
|
25860
25949
|
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
25861
25950
|
return { ok: false, reason: "cwd dışı yol" };
|
|
@@ -26119,16 +26208,16 @@ var FRAMEWORKS = [
|
|
|
26119
26208
|
"node-server"
|
|
26120
26209
|
];
|
|
26121
26210
|
function bail() {
|
|
26122
|
-
|
|
26211
|
+
p4.cancel("İptal edildi.");
|
|
26123
26212
|
process.exit(0);
|
|
26124
26213
|
}
|
|
26125
26214
|
async function runWizard(opts) {
|
|
26126
26215
|
if (process.stdout.isTTY)
|
|
26127
26216
|
process.stdout.write(banner());
|
|
26128
|
-
|
|
26217
|
+
p4.intro(c3.dim("otonom kurulum başlıyor — auth → workspace → install → wire"));
|
|
26129
26218
|
const TOTAL = 6;
|
|
26130
26219
|
const phase = (n2, label) => {
|
|
26131
|
-
|
|
26220
|
+
p4.log.step(`${c3.dim(`[${n2}/${TOTAL}]`)} ${c3.bold(label)}`);
|
|
26132
26221
|
};
|
|
26133
26222
|
phase(1, "Kimlik doğrulama");
|
|
26134
26223
|
const auth = await ensureAuth({
|
|
@@ -26145,18 +26234,18 @@ async function runWizard(opts) {
|
|
|
26145
26234
|
if (opts.framework && FRAMEWORKS.includes(opts.framework)) {
|
|
26146
26235
|
framework = opts.framework;
|
|
26147
26236
|
} else if (!opts.yes) {
|
|
26148
|
-
const ok = await
|
|
26237
|
+
const ok = await p4.confirm({
|
|
26149
26238
|
message: `Saptanan: ${detected.framework} (${detected.packageManager}). Doğru mu?`
|
|
26150
26239
|
});
|
|
26151
|
-
if (
|
|
26240
|
+
if (p4.isCancel(ok))
|
|
26152
26241
|
bail();
|
|
26153
26242
|
if (!ok) {
|
|
26154
|
-
const choice = await
|
|
26243
|
+
const choice = await p4.select({
|
|
26155
26244
|
message: "Framework seç",
|
|
26156
26245
|
options: FRAMEWORKS.map((f3) => ({ value: f3, label: f3 })),
|
|
26157
26246
|
initialValue: detected.framework
|
|
26158
26247
|
});
|
|
26159
|
-
if (
|
|
26248
|
+
if (p4.isCancel(choice))
|
|
26160
26249
|
bail();
|
|
26161
26250
|
framework = choice;
|
|
26162
26251
|
}
|
|
@@ -26176,17 +26265,21 @@ async function runWizard(opts) {
|
|
|
26176
26265
|
if (approved)
|
|
26177
26266
|
approvedEvents = approved;
|
|
26178
26267
|
} else {
|
|
26179
|
-
|
|
26268
|
+
p4.log.info("AI planı yok — autocapture + sektör paketi (deterministik floor).");
|
|
26180
26269
|
}
|
|
26181
26270
|
}
|
|
26271
|
+
let featuresResult = { selected: [], registered: false };
|
|
26272
|
+
if (authed) {
|
|
26273
|
+
featuresResult = await runFeatures(client, project, { yes: opts.yes, authed });
|
|
26274
|
+
}
|
|
26182
26275
|
phase(4, "SDK kurulumu");
|
|
26183
26276
|
let installed = false;
|
|
26184
26277
|
if (opts.noInstall) {
|
|
26185
|
-
|
|
26278
|
+
p4.log.info(`SDK kurulumu atlandı — elle: ${plan.installCommand}`);
|
|
26186
26279
|
} else if (!detected.hasPackageJson) {
|
|
26187
|
-
|
|
26280
|
+
p4.log.warn("package.json yok — script tag ile kur: https://cdn.gurulu.io/t.js");
|
|
26188
26281
|
} else {
|
|
26189
|
-
const s2 =
|
|
26282
|
+
const s2 = p4.spinner();
|
|
26190
26283
|
s2.start(`${plan.sdk} kuruluyor (${plan.installCommand})…`);
|
|
26191
26284
|
const res = await execInstall(plan, { cwd: opts.cwd });
|
|
26192
26285
|
if (res.ok) {
|
|
@@ -26213,7 +26306,7 @@ async function runWizard(opts) {
|
|
|
26213
26306
|
if (auth.apiKey.startsWith("sk_")) {
|
|
26214
26307
|
vars.push({ key: k2.key, value: auth.apiKey });
|
|
26215
26308
|
} else {
|
|
26216
|
-
|
|
26309
|
+
p4.log.warn("GURULU_SECRET_KEY atlandı (login token workspace sk_ anahtarı değil). Dashboard → Settings → API Keys'ten server key oluşturup .env'e elle ekle.");
|
|
26217
26310
|
}
|
|
26218
26311
|
}
|
|
26219
26312
|
}
|
|
@@ -26233,7 +26326,7 @@ async function runWizard(opts) {
|
|
|
26233
26326
|
}
|
|
26234
26327
|
let registeredCount = 0;
|
|
26235
26328
|
if (approvedEvents.length > 0) {
|
|
26236
|
-
const s2 =
|
|
26329
|
+
const s2 = p4.spinner();
|
|
26237
26330
|
s2.start("Yeni eventler registry kuyruguna oneriliyor…");
|
|
26238
26331
|
const res = await registerNewEvents(client, approvedEvents);
|
|
26239
26332
|
registeredCount = res.registered.length;
|
|
@@ -26242,29 +26335,29 @@ async function runWizard(opts) {
|
|
|
26242
26335
|
let wiredCount = 0;
|
|
26243
26336
|
if (approvedEvents.length > 0) {
|
|
26244
26337
|
if (opts.noAi) {
|
|
26245
|
-
|
|
26338
|
+
p4.log.message(`Capture — şu çağrıları ekle:
|
|
26246
26339
|
${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
26247
26340
|
} else {
|
|
26248
26341
|
const wireFiles = gatherContext({ cwd: opts.cwd }).files.map((f3) => f3.path);
|
|
26249
26342
|
const snapshots = new Map;
|
|
26250
|
-
const s2 =
|
|
26343
|
+
const s2 = p4.spinner();
|
|
26251
26344
|
s2.start("AI capture wiring (kod düzenleniyor)…");
|
|
26252
26345
|
const outcome = await runWireAgent(client, { cwd: opts.cwd, events: approvedEvents, identifyHint, files: wireFiles }, snapshots);
|
|
26253
26346
|
s2.stop(`wire: ${outcome.changedFiles.length} dosya / ${outcome.steps} adım (${outcome.stoppedReason})`);
|
|
26254
26347
|
if (outcome.changedFiles.length > 0) {
|
|
26255
|
-
|
|
26256
|
-
const keep = opts.yes ? true : await
|
|
26348
|
+
p4.log.message(formatWireDiff(opts.cwd, snapshots));
|
|
26349
|
+
const keep = opts.yes ? true : await p4.confirm({
|
|
26257
26350
|
message: `${outcome.changedFiles.length} dosyadaki wire değişikliklerini tut?`
|
|
26258
26351
|
});
|
|
26259
|
-
if (
|
|
26352
|
+
if (p4.isCancel(keep) || !keep) {
|
|
26260
26353
|
restoreSnapshots(opts.cwd, snapshots);
|
|
26261
|
-
|
|
26262
|
-
|
|
26354
|
+
p4.log.info("Wire geri alındı — capture snippet rehberi:");
|
|
26355
|
+
p4.log.message(captureGuide(approvedEvents, identifyHint, isNode));
|
|
26263
26356
|
} else {
|
|
26264
26357
|
wiredCount = outcome.changedFiles.length;
|
|
26265
26358
|
}
|
|
26266
26359
|
} else {
|
|
26267
|
-
|
|
26360
|
+
p4.log.message(`Capture (AI gömemedi → snippet-göster) — şu çağrıları ekle:
|
|
26268
26361
|
${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
26269
26362
|
}
|
|
26270
26363
|
}
|
|
@@ -26283,15 +26376,18 @@ ${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
|
26283
26376
|
if (wiredCount > 0)
|
|
26284
26377
|
lines.push(`✓ ${wiredCount} dosya AI ile capture wire edildi`);
|
|
26285
26378
|
}
|
|
26379
|
+
if (featuresResult.registered && featuresResult.selected.length > 0) {
|
|
26380
|
+
lines.push(`✓ özellikler: ${featuresResult.selected.map((f3) => f3.key).join(", ")} kuruldu`);
|
|
26381
|
+
}
|
|
26286
26382
|
lines.push(`✓ .gurulu/config.json${pulled ? " + registry pull" : ""}`);
|
|
26287
|
-
|
|
26383
|
+
p4.note(lines.join(`
|
|
26288
26384
|
`), c3.neon("✦ Değişiklikler"));
|
|
26289
26385
|
if (inj.strategy !== "prepend-entry" || inj.reason === "no-entry") {
|
|
26290
|
-
|
|
26386
|
+
p4.log.info(`Wire: ${inj.wireHint ?? plan.placementHint}`);
|
|
26291
26387
|
if (inj.strategy === "manual")
|
|
26292
|
-
|
|
26388
|
+
p4.log.message(plan.initSnippet);
|
|
26293
26389
|
}
|
|
26294
|
-
|
|
26390
|
+
p4.outro(`${c3.neon("\uD83E\uDD89 Hazır!")} ${c3.dim("Doğrula:")} ${c3.bold("gurulu doctor")} ${c3.dim("·")} ${c3.dim("Dashboard:")} ${c3.cyan("https://dashboard.gurulu.io/app?onboard=done")}`);
|
|
26295
26391
|
}
|
|
26296
26392
|
async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
26297
26393
|
if (opts.writeKey) {
|
|
@@ -26314,7 +26410,7 @@ async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
|
26314
26410
|
selected = CREATE;
|
|
26315
26411
|
} else {
|
|
26316
26412
|
const initial = list.find((w2) => w2.workspace_id === authWorkspaceId)?.workspace_id ?? list[0]?.workspace_id ?? CREATE;
|
|
26317
|
-
const choice = await
|
|
26413
|
+
const choice = await p4.select({
|
|
26318
26414
|
message: "Workspace seç",
|
|
26319
26415
|
options: [
|
|
26320
26416
|
...list.map((w2) => ({ value: w2.workspace_id, label: w2.name, hint: w2.slug })),
|
|
@@ -26322,26 +26418,26 @@ async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
|
26322
26418
|
],
|
|
26323
26419
|
initialValue: initial
|
|
26324
26420
|
});
|
|
26325
|
-
if (
|
|
26421
|
+
if (p4.isCancel(choice))
|
|
26326
26422
|
bail();
|
|
26327
26423
|
selected = choice;
|
|
26328
26424
|
}
|
|
26329
26425
|
if (selected === CREATE) {
|
|
26330
|
-
const name = await
|
|
26426
|
+
const name = await p4.text({
|
|
26331
26427
|
message: "Workspace adı",
|
|
26332
26428
|
placeholder: "My App",
|
|
26333
26429
|
validate: (v2) => v2.trim() ? undefined : "gerekli"
|
|
26334
26430
|
});
|
|
26335
|
-
if (
|
|
26431
|
+
if (p4.isCancel(name))
|
|
26336
26432
|
bail();
|
|
26337
|
-
const domain = await
|
|
26433
|
+
const domain = await p4.text({
|
|
26338
26434
|
message: "Domain",
|
|
26339
26435
|
placeholder: "example.com",
|
|
26340
26436
|
validate: (v2) => v2.trim().length >= 3 ? undefined : "geçerli domain gerekli"
|
|
26341
26437
|
});
|
|
26342
|
-
if (
|
|
26438
|
+
if (p4.isCancel(domain))
|
|
26343
26439
|
bail();
|
|
26344
|
-
const s2 =
|
|
26440
|
+
const s2 = p4.spinner();
|
|
26345
26441
|
s2.start("Workspace oluşturuluyor…");
|
|
26346
26442
|
const created = await client.createWorkspace({
|
|
26347
26443
|
name: String(name).trim(),
|
|
@@ -26666,7 +26762,7 @@ import { execFile as execFile2 } from "node:child_process";
|
|
|
26666
26762
|
import { existsSync as existsSync11, readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync10 } from "node:fs";
|
|
26667
26763
|
import { join as join10 } from "node:path";
|
|
26668
26764
|
import { promisify as promisify2 } from "node:util";
|
|
26669
|
-
import * as
|
|
26765
|
+
import * as p5 from "@clack/prompts";
|
|
26670
26766
|
var pexec2 = promisify2(execFile2);
|
|
26671
26767
|
var ENV_FILES = [".env.local", ".env"];
|
|
26672
26768
|
var GURULU_PREFIXES = ["GURULU_", "NEXT_PUBLIC_GURULU", "VITE_GURULU"];
|
|
@@ -26693,23 +26789,23 @@ var uninstallCmd = defineCommand({
|
|
|
26693
26789
|
const config = readProjectConfig(cwd);
|
|
26694
26790
|
const detected = detectProject(cwd);
|
|
26695
26791
|
const pkg = config?.sdk_preference === "node" ? "@gurulu/node" : "@gurulu/web";
|
|
26696
|
-
|
|
26697
|
-
|
|
26792
|
+
p5.intro("Gurulu uninstall");
|
|
26793
|
+
p5.note([
|
|
26698
26794
|
`• SDK kaldır: ${pkg} (${detected.packageManager})`,
|
|
26699
26795
|
`• env temizle: ${ENV_FILES.join(", ")} (GURULU_* anahtarları)`,
|
|
26700
26796
|
"• .gurulu/ dizinini sil"
|
|
26701
26797
|
].join(`
|
|
26702
26798
|
`), "Şunlar yapılacak");
|
|
26703
26799
|
if (!args.yes) {
|
|
26704
|
-
const ok = await
|
|
26705
|
-
if (
|
|
26706
|
-
|
|
26800
|
+
const ok = await p5.confirm({ message: "Devam edilsin mi?" });
|
|
26801
|
+
if (p5.isCancel(ok) || !ok) {
|
|
26802
|
+
p5.cancel("İptal.");
|
|
26707
26803
|
process.exit(0);
|
|
26708
26804
|
}
|
|
26709
26805
|
}
|
|
26710
26806
|
if (!args["no-deps"] && detected.hasPackageJson) {
|
|
26711
26807
|
const { bin, args: a2 } = removeCmd(detected.packageManager, pkg);
|
|
26712
|
-
const s2 =
|
|
26808
|
+
const s2 = p5.spinner();
|
|
26713
26809
|
s2.start(`${pkg} kaldırılıyor…`);
|
|
26714
26810
|
try {
|
|
26715
26811
|
await pexec2(bin, a2, { cwd, timeout: 120000 });
|
|
@@ -26732,7 +26828,7 @@ var uninstallCmd = defineCommand({
|
|
|
26732
26828
|
const guruluDir = join10(cwd, ".gurulu");
|
|
26733
26829
|
if (existsSync11(guruluDir))
|
|
26734
26830
|
rmSync(guruluDir, { recursive: true, force: true });
|
|
26735
|
-
|
|
26831
|
+
p5.outro(`Kaldırıldı. env: ${cleaned.join(", ") || "değişiklik yok"} · .gurulu silindi. (Koddaki init/track çağrılarını elle çıkar.)`);
|
|
26736
26832
|
}
|
|
26737
26833
|
});
|
|
26738
26834
|
|
package/dist/lib/detect.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type Framework = 'next' | 'react' | 'vue' | 'nuxt' | 'svelte' | 'astro' | 'vite' | 'express' | 'fastify' | 'hono' | 'koa' | 'node-server' | 'unknown';
|
|
2
2
|
export type Runtime = 'browser' | 'node' | 'unknown';
|
|
3
|
+
export type LlmFramework = 'openai' | 'anthropic' | 'langchain' | 'google-genai' | 'vercel-ai' | 'cohere' | 'mistral' | 'ollama';
|
|
3
4
|
export type PackageManager = 'bun' | 'pnpm' | 'yarn' | 'npm';
|
|
4
5
|
export interface DetectedProject {
|
|
5
6
|
dir: string;
|
|
@@ -8,6 +9,8 @@ export interface DetectedProject {
|
|
|
8
9
|
runtime: Runtime;
|
|
9
10
|
packageManager: PackageManager;
|
|
10
11
|
packageJson: PackageJsonShape | null;
|
|
12
|
+
/** M46 (K31) — tespit edilen LLM/AI bağımlılıkları (boş = yok). */
|
|
13
|
+
llmFrameworks: LlmFramework[];
|
|
11
14
|
}
|
|
12
15
|
interface PackageJsonShape {
|
|
13
16
|
name?: string;
|
|
@@ -22,6 +25,8 @@ interface PackageJsonShape {
|
|
|
22
25
|
export declare function detectPackageManager(dir: string): PackageManager;
|
|
23
26
|
export declare function detectFramework(pkg: PackageJsonShape | null, dir: string): Framework;
|
|
24
27
|
export declare function frameworkRuntime(fw: Framework): Runtime;
|
|
28
|
+
/** package.json dependencies içinde LLM/AI SDK'larını tespit eder (dedup). */
|
|
29
|
+
export declare function detectLlmFrameworks(pkg: PackageJsonShape | null): LlmFramework[];
|
|
25
30
|
export declare function detectProject(dir: string): DetectedProject;
|
|
26
31
|
export {};
|
|
27
32
|
//# sourceMappingURL=detect.d.ts.map
|
package/dist/lib/detect.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/lib/detect.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,OAAO,GACP,KAAK,GACL,MAAM,GACN,QAAQ,GACR,OAAO,GACP,MAAM,GACN,SAAS,GACT,SAAS,GACT,MAAM,GACN,KAAK,GACL,aAAa,GACb,SAAS,CAAC;AAEd,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/lib/detect.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,OAAO,GACP,KAAK,GACL,MAAM,GACN,QAAQ,GACR,OAAO,GACP,MAAM,GACN,SAAS,GACT,SAAS,GACT,MAAM,GACN,KAAK,GACL,aAAa,GACb,SAAS,CAAC;AAEd,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAGrD,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,WAAW,GACX,WAAW,GACX,cAAc,GACd,WAAW,GACX,QAAQ,GACR,SAAS,GACT,QAAQ,CAAC;AAeb,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrC,mEAAmE;IACnE,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAiBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAchE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAmBpF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAmBvD;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAAG,YAAY,EAAE,CAMhF;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAY1D"}
|
package/dist/lib/detect.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
// src/lib/detect.ts
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join, parse } from "node:path";
|
|
4
|
+
var LLM_DEP_MAP = {
|
|
5
|
+
openai: "openai",
|
|
6
|
+
"@anthropic-ai/sdk": "anthropic",
|
|
7
|
+
"@langchain/core": "langchain",
|
|
8
|
+
langchain: "langchain",
|
|
9
|
+
"@google/generative-ai": "google-genai",
|
|
10
|
+
ai: "vercel-ai",
|
|
11
|
+
"cohere-ai": "cohere",
|
|
12
|
+
"@mistralai/mistralai": "mistral",
|
|
13
|
+
ollama: "ollama"
|
|
14
|
+
};
|
|
4
15
|
function readPackageJson(dir) {
|
|
5
16
|
const p = join(dir, "package.json");
|
|
6
17
|
if (!existsSync(p))
|
|
@@ -86,6 +97,14 @@ function frameworkRuntime(fw) {
|
|
|
86
97
|
return "unknown";
|
|
87
98
|
}
|
|
88
99
|
}
|
|
100
|
+
function detectLlmFrameworks(pkg) {
|
|
101
|
+
const found = new Set;
|
|
102
|
+
for (const [dep, fw] of Object.entries(LLM_DEP_MAP)) {
|
|
103
|
+
if (hasDep(pkg, dep))
|
|
104
|
+
found.add(fw);
|
|
105
|
+
}
|
|
106
|
+
return [...found];
|
|
107
|
+
}
|
|
89
108
|
function detectProject(dir) {
|
|
90
109
|
const pkg = readPackageJson(dir);
|
|
91
110
|
const framework = detectFramework(pkg, dir);
|
|
@@ -95,12 +114,14 @@ function detectProject(dir) {
|
|
|
95
114
|
framework,
|
|
96
115
|
runtime: frameworkRuntime(framework),
|
|
97
116
|
packageManager: detectPackageManager(dir),
|
|
98
|
-
packageJson: pkg
|
|
117
|
+
packageJson: pkg,
|
|
118
|
+
llmFrameworks: detectLlmFrameworks(pkg)
|
|
99
119
|
};
|
|
100
120
|
}
|
|
101
121
|
export {
|
|
102
122
|
frameworkRuntime,
|
|
103
123
|
detectProject,
|
|
104
124
|
detectPackageManager,
|
|
125
|
+
detectLlmFrameworks,
|
|
105
126
|
detectFramework
|
|
106
127
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ApiClient } from '../lib/api.ts';
|
|
2
|
+
import { type DetectedProject } from '../lib/detect.ts';
|
|
3
|
+
export type FeatureKey = 'error' | 'llm' | 'activation';
|
|
4
|
+
export interface FeatureOption {
|
|
5
|
+
key: FeatureKey;
|
|
6
|
+
label: string;
|
|
7
|
+
/** multiselect hint (kısa). */
|
|
8
|
+
detail: string;
|
|
9
|
+
/** kurulumdan sonra gösterilen "nasıl açılır" snippet'i. */
|
|
10
|
+
enableHint: string;
|
|
11
|
+
/** öneri (pre-checked). */
|
|
12
|
+
recommended: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Tespite göre kurulabilir özellikler. */
|
|
15
|
+
export declare function availableFeatures(detected: DetectedProject): FeatureOption[];
|
|
16
|
+
export interface FeaturesResult {
|
|
17
|
+
selected: FeatureOption[];
|
|
18
|
+
registered: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Özellikleri sun + seç + gateway'e kaydet. authed değilse atlar (registration
|
|
22
|
+
* apiKey gerektirir). `--yes` → önerilenler otomatik.
|
|
23
|
+
*/
|
|
24
|
+
export declare function runFeatures(client: ApiClient, detected: DetectedProject, opts: {
|
|
25
|
+
yes?: boolean;
|
|
26
|
+
authed: boolean;
|
|
27
|
+
}): Promise<FeaturesResult>;
|
|
28
|
+
//# sourceMappingURL=features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/wizard/features.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,KAAK,eAAe,EAAoB,MAAM,kBAAkB,CAAC;AAG1E,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,GAAG,YAAY,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,aAAa,EAAE,CAsC5E;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACvC,OAAO,CAAC,cAAc,CAAC,CAqCzB"}
|
package/dist/wizard/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/wizard/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/wizard/run.ts"],"names":[],"mappings":"AAiCA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAsBD,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkOlE"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gurulu/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
|
-
"description": "Gurulu CLI. init / pull / push / validate / doctor
|
|
10
|
+
"description": "Gurulu CLI. init / pull / push / validate / doctor \u2014 registry as code, local schema sync.",
|
|
11
11
|
"homepage": "https://gurulu.io",
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|