selftune 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -35
- package/apps/local-dashboard/dist/assets/index-BZVLv70T.js +16 -0
- package/apps/local-dashboard/dist/assets/{index-CRtLkBTi.css → index-Bs3Y4ixf.css} +1 -1
- package/apps/local-dashboard/dist/assets/{vendor-react-BQH_6WrG.js → vendor-react-BXP54cYo.js} +4 -4
- package/apps/local-dashboard/dist/assets/{vendor-table-dK1QMLq9.js → vendor-table-DTF_SXoy.js} +1 -1
- package/apps/local-dashboard/dist/assets/{vendor-ui-CO2mrx6e.js → vendor-ui-CWU0d1wd.js} +66 -66
- package/apps/local-dashboard/dist/index.html +15 -15
- package/bin/selftune.cjs +1 -1
- package/cli/selftune/activation-rules.ts +37 -18
- package/cli/selftune/agent-guidance.ts +16 -16
- package/cli/selftune/alpha-identity.ts +1 -2
- package/cli/selftune/alpha-upload/build-payloads.ts +18 -2
- package/cli/selftune/alpha-upload/flush.ts +2 -2
- package/cli/selftune/alpha-upload/stage-canonical.ts +106 -3
- package/cli/selftune/auth/device-code.ts +32 -0
- package/cli/selftune/auto-update.ts +12 -0
- package/cli/selftune/badge/badge.ts +1 -0
- package/cli/selftune/canonical-export.ts +5 -0
- package/cli/selftune/claude-agents.ts +154 -0
- package/cli/selftune/contribute/bundle.ts +2 -0
- package/cli/selftune/contribute/contribute.ts +1 -0
- package/cli/selftune/cron/setup.ts +2 -2
- package/cli/selftune/dashboard-contract.ts +1 -1
- package/cli/selftune/dashboard-server.ts +11 -52
- package/cli/selftune/eval/hooks-to-evals.ts +13 -6
- package/cli/selftune/eval/import-skillsbench.ts +1 -0
- package/cli/selftune/eval/synthetic-evals.ts +2 -3
- package/cli/selftune/eval/unit-test.ts +1 -0
- package/cli/selftune/evolution/deploy-proposal.ts +1 -0
- package/cli/selftune/evolution/evolve-body.ts +93 -6
- package/cli/selftune/evolution/evolve.ts +0 -1
- package/cli/selftune/evolution/propose-body.ts +3 -2
- package/cli/selftune/evolution/propose-routing.ts +3 -2
- package/cli/selftune/evolution/refine-body.ts +3 -2
- package/cli/selftune/export.ts +1 -0
- package/cli/selftune/grading/auto-grade.ts +1 -0
- package/cli/selftune/grading/grade-session.ts +9 -0
- package/cli/selftune/hooks/auto-activate.ts +6 -0
- package/cli/selftune/hooks/evolution-guard.ts +12 -15
- package/cli/selftune/hooks/prompt-log.ts +1 -0
- package/cli/selftune/hooks/session-stop.ts +34 -40
- package/cli/selftune/hooks/skill-change-guard.ts +1 -0
- package/cli/selftune/hooks/skill-eval.ts +1 -1
- package/cli/selftune/index.ts +23 -14
- package/cli/selftune/ingestors/claude-replay.ts +1 -0
- package/cli/selftune/ingestors/codex-rollout.ts +1 -0
- package/cli/selftune/ingestors/codex-wrapper.ts +1 -0
- package/cli/selftune/ingestors/openclaw-ingest.ts +1 -0
- package/cli/selftune/ingestors/opencode-ingest.ts +1 -0
- package/cli/selftune/init.ts +197 -96
- package/cli/selftune/localdb/db.ts +1 -0
- package/cli/selftune/localdb/direct-write.ts +93 -12
- package/cli/selftune/localdb/materialize.ts +2 -0
- package/cli/selftune/localdb/queries.ts +210 -0
- package/cli/selftune/localdb/schema.ts +72 -1
- package/cli/selftune/monitoring/watch.ts +1 -0
- package/cli/selftune/normalization.ts +4 -0
- package/cli/selftune/observability.ts +14 -7
- package/cli/selftune/orchestrate.ts +15 -37
- package/cli/selftune/repair/skill-usage.ts +7 -3
- package/cli/selftune/routes/orchestrate-runs.ts +1 -0
- package/cli/selftune/routes/overview.ts +1 -0
- package/cli/selftune/routes/skill-report.ts +1 -0
- package/cli/selftune/sync.ts +31 -1
- package/cli/selftune/types.ts +2 -2
- package/cli/selftune/uninstall.ts +412 -0
- package/cli/selftune/utils/canonical-log.ts +2 -0
- package/cli/selftune/utils/jsonl.ts +1 -0
- package/cli/selftune/utils/llm-call.ts +131 -3
- package/cli/selftune/utils/skill-log.ts +1 -0
- package/cli/selftune/utils/transcript.ts +1 -0
- package/cli/selftune/utils/trigger-check.ts +1 -1
- package/cli/selftune/workflows/skill-md-writer.ts +5 -5
- package/cli/selftune/workflows/workflows.ts +1 -0
- package/package.json +38 -33
- package/packages/telemetry-contract/fixtures/golden.test.ts +1 -0
- package/packages/telemetry-contract/package.json +3 -3
- package/packages/telemetry-contract/src/index.ts +0 -1
- package/packages/telemetry-contract/src/schemas.ts +6 -24
- package/packages/telemetry-contract/tests/compatibility.test.ts +1 -0
- package/packages/ui/README.md +35 -34
- package/packages/ui/package.json +3 -3
- package/packages/ui/src/components/ActivityTimeline.tsx +49 -42
- package/packages/ui/src/components/EvidenceViewer.tsx +306 -182
- package/packages/ui/src/components/EvolutionTimeline.tsx +83 -72
- package/packages/ui/src/components/InfoTip.tsx +4 -3
- package/packages/ui/src/components/OrchestrateRunsPanel.tsx +60 -53
- package/packages/ui/src/components/section-cards.tsx +19 -24
- package/packages/ui/src/components/skill-health-grid.tsx +213 -193
- package/packages/ui/src/lib/constants.tsx +1 -0
- package/packages/ui/src/primitives/badge.tsx +12 -15
- package/packages/ui/src/primitives/button.tsx +7 -7
- package/packages/ui/src/primitives/card.tsx +15 -26
- package/packages/ui/src/primitives/checkbox.tsx +7 -8
- package/packages/ui/src/primitives/collapsible.tsx +5 -5
- package/packages/ui/src/primitives/dropdown-menu.tsx +45 -55
- package/packages/ui/src/primitives/label.tsx +6 -6
- package/packages/ui/src/primitives/select.tsx +28 -37
- package/packages/ui/src/primitives/table.tsx +17 -44
- package/packages/ui/src/primitives/tabs.tsx +14 -21
- package/packages/ui/src/primitives/tooltip.tsx +10 -22
- package/skill/SKILL.md +72 -59
- package/skill/Workflows/AlphaUpload.md +4 -4
- package/skill/Workflows/AutoActivation.md +11 -6
- package/skill/Workflows/Badge.md +22 -16
- package/skill/Workflows/Baseline.md +34 -36
- package/skill/Workflows/Composability.md +16 -11
- package/skill/Workflows/Contribute.md +26 -21
- package/skill/Workflows/Cron.md +23 -22
- package/skill/Workflows/Dashboard.md +40 -40
- package/skill/Workflows/Doctor.md +40 -34
- package/skill/Workflows/Evals.md +48 -47
- package/skill/Workflows/EvolutionMemory.md +31 -21
- package/skill/Workflows/Evolve.md +84 -82
- package/skill/Workflows/EvolveBody.md +58 -47
- package/skill/Workflows/Grade.md +16 -13
- package/skill/Workflows/ImportSkillsBench.md +9 -6
- package/skill/Workflows/Ingest.md +36 -21
- package/skill/Workflows/Initialize.md +138 -97
- package/skill/Workflows/Orchestrate.md +22 -16
- package/skill/Workflows/Replay.md +12 -7
- package/skill/Workflows/Rollback.md +13 -6
- package/skill/Workflows/Schedule.md +6 -6
- package/skill/Workflows/Sync.md +18 -11
- package/skill/Workflows/UnitTest.md +28 -17
- package/skill/Workflows/Watch.md +28 -21
- package/skill/agents/diagnosis-analyst.md +11 -0
- package/skill/agents/evolution-reviewer.md +15 -1
- package/skill/agents/integration-guide.md +10 -0
- package/skill/agents/pattern-analyst.md +12 -1
- package/skill/references/grading-methodology.md +23 -24
- package/skill/references/interactive-config.md +7 -7
- package/skill/references/invocation-taxonomy.md +22 -20
- package/skill/references/logs.md +20 -6
- package/skill/references/setup-patterns.md +4 -2
- package/.claude/agents/diagnosis-analyst.md +0 -156
- package/.claude/agents/evolution-reviewer.md +0 -180
- package/.claude/agents/integration-guide.md +0 -212
- package/.claude/agents/pattern-analyst.md +0 -160
- package/apps/local-dashboard/dist/assets/index-Bk9vSHHd.js +0 -15
package/cli/selftune/export.ts
CHANGED
|
@@ -101,6 +101,7 @@ Options:
|
|
|
101
101
|
telRecords = querySessionTelemetry(db) as SessionTelemetryRecord[];
|
|
102
102
|
skillUsageRecords = querySkillUsageRecords(db) as SkillUsageRecord[];
|
|
103
103
|
} else {
|
|
104
|
+
// Intentional JSONL fallback: custom --telemetry-log path overrides SQLite reads
|
|
104
105
|
telRecords = readJsonl<SessionTelemetryRecord>(telemetryLog);
|
|
105
106
|
skillUsageRecords = [];
|
|
106
107
|
}
|
|
@@ -812,6 +812,7 @@ Options:
|
|
|
812
812
|
telRecords = querySessionTelemetry(db) as SessionTelemetryRecord[];
|
|
813
813
|
skillUsageRecords = querySkillUsageRecords(db) as SkillUsageRecord[];
|
|
814
814
|
} else {
|
|
815
|
+
// Intentional JSONL fallback: custom --telemetry-log path overrides SQLite reads
|
|
815
816
|
telRecords = readJsonl<SessionTelemetryRecord>(telemetryLog);
|
|
816
817
|
skillUsageRecords = [];
|
|
817
818
|
}
|
|
@@ -883,6 +884,14 @@ Options:
|
|
|
883
884
|
}
|
|
884
885
|
writeFileSync(outputPath, JSON.stringify(result, null, 2), "utf-8");
|
|
885
886
|
|
|
887
|
+
// Persist to SQLite for upload staging (fail-open)
|
|
888
|
+
try {
|
|
889
|
+
const { writeGradingResultToDb } = await import("../localdb/direct-write.js");
|
|
890
|
+
writeGradingResultToDb(result);
|
|
891
|
+
} catch {
|
|
892
|
+
// fail-open: grading file is already written above
|
|
893
|
+
}
|
|
894
|
+
|
|
886
895
|
printSummary(result);
|
|
887
896
|
console.log(`\nWrote ${outputPath}`);
|
|
888
897
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { dirname } from "node:path";
|
|
14
|
+
|
|
14
15
|
import {
|
|
15
16
|
CLAUDE_SETTINGS_PATH,
|
|
16
17
|
EVOLUTION_AUDIT_LOG,
|
|
@@ -158,6 +159,11 @@ if (import.meta.main) {
|
|
|
158
159
|
// Dynamically import default rules (keeps hook file lightweight)
|
|
159
160
|
const { DEFAULT_RULES } = await import("../activation-rules.js");
|
|
160
161
|
|
|
162
|
+
/**
|
|
163
|
+
* The *_log_path fields exist for test overrides only; default code paths
|
|
164
|
+
* in activation-rules.ts read from SQLite when the path matches the
|
|
165
|
+
* constant (QUERY_LOG, EVOLUTION_AUDIT_LOG, etc.).
|
|
166
|
+
*/
|
|
161
167
|
const ctx: ActivationContext = {
|
|
162
168
|
session_id: sessionId,
|
|
163
169
|
query_log_path: QUERY_LOG,
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
import { existsSync, readFileSync } from "node:fs";
|
|
18
18
|
import { basename, dirname, join } from "node:path";
|
|
19
|
-
import { EVOLUTION_AUDIT_LOG, SELFTUNE_CONFIG_DIR } from "../constants.js";
|
|
20
19
|
|
|
20
|
+
import { EVOLUTION_AUDIT_LOG, SELFTUNE_CONFIG_DIR } from "../constants.js";
|
|
21
21
|
import type { PreToolUsePayload } from "../types.js";
|
|
22
22
|
import { readJsonl } from "../utils/jsonl.js";
|
|
23
23
|
|
|
@@ -35,12 +35,12 @@ function extractSkillName(filePath: string): string {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
// ---------------------------------------------------------------------------
|
|
38
|
-
// Active monitoring check (
|
|
38
|
+
// Active monitoring check (SQLite-first — JSONL only for test/custom paths)
|
|
39
39
|
// ---------------------------------------------------------------------------
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Check if a skill has an active deployed evolution (meaning it's under monitoring).
|
|
43
|
-
*
|
|
43
|
+
* SQLite is the default read path; JSONL is used only for test/custom-path overrides.
|
|
44
44
|
*
|
|
45
45
|
* A skill is "actively monitored" if its last audit action is "deployed".
|
|
46
46
|
* If the last action is "rolled_back", it's no longer monitored.
|
|
@@ -49,21 +49,18 @@ export async function checkActiveMonitoring(
|
|
|
49
49
|
skillName: string,
|
|
50
50
|
auditLogPath: string,
|
|
51
51
|
): Promise<boolean> {
|
|
52
|
-
//
|
|
52
|
+
// SQLite is the default path; JSONL fallback only for non-default paths (tests)
|
|
53
53
|
let entries: Array<{ skill_name?: string; action: string }>;
|
|
54
54
|
if (auditLogPath === EVOLUTION_AUDIT_LOG) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}>;
|
|
63
|
-
} catch {
|
|
64
|
-
entries = readJsonl<{ skill_name?: string; action: string }>(auditLogPath);
|
|
65
|
-
}
|
|
55
|
+
const { getDb } = await import("../localdb/db.js");
|
|
56
|
+
const { queryEvolutionAudit } = await import("../localdb/queries.js");
|
|
57
|
+
const db = getDb();
|
|
58
|
+
entries = queryEvolutionAudit(db, skillName) as Array<{
|
|
59
|
+
skill_name?: string;
|
|
60
|
+
action: string;
|
|
61
|
+
}>;
|
|
66
62
|
} else {
|
|
63
|
+
// test/custom-path fallback
|
|
67
64
|
entries = readJsonl<{ skill_name?: string; action: string }>(auditLogPath);
|
|
68
65
|
}
|
|
69
66
|
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { execSync } from "node:child_process";
|
|
12
|
-
import {
|
|
13
|
-
import { CANONICAL_LOG, ORCHESTRATE_LOCK, TELEMETRY_LOG } from "../constants.js";
|
|
12
|
+
import { readFileSync } from "node:fs";
|
|
14
13
|
|
|
14
|
+
import { CANONICAL_LOG, ORCHESTRATE_LOCK, TELEMETRY_LOG } from "../constants.js";
|
|
15
15
|
import {
|
|
16
16
|
appendCanonicalRecords,
|
|
17
17
|
buildCanonicalExecutionFact,
|
|
@@ -25,6 +25,22 @@ import { parseTranscript } from "../utils/transcript.js";
|
|
|
25
25
|
|
|
26
26
|
const LOCK_STALE_MS = 30 * 60 * 1000;
|
|
27
27
|
|
|
28
|
+
interface ReactiveSpawnDeps {
|
|
29
|
+
spawnOrchestrate?: () => boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function hasFreshOrchestrateLock(lockPath: string): boolean {
|
|
33
|
+
try {
|
|
34
|
+
const lockContent = readFileSync(lockPath, "utf8");
|
|
35
|
+
const lock = JSON.parse(lockContent) as { timestamp?: string };
|
|
36
|
+
if (typeof lock.timestamp !== "string") return false;
|
|
37
|
+
const lockAge = Date.now() - new Date(lock.timestamp).getTime();
|
|
38
|
+
return Number.isFinite(lockAge) && lockAge < LOCK_STALE_MS;
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
/**
|
|
29
45
|
* Check for pending improvement signals and spawn a focused orchestrate run
|
|
30
46
|
* in the background if warranted. Fire-and-forget — the hook exits immediately.
|
|
@@ -33,6 +49,7 @@ const LOCK_STALE_MS = 30 * 60 * 1000;
|
|
|
33
49
|
*/
|
|
34
50
|
export async function maybeSpawnReactiveOrchestrate(
|
|
35
51
|
lockPath: string = ORCHESTRATE_LOCK,
|
|
52
|
+
deps: ReactiveSpawnDeps = {},
|
|
36
53
|
): Promise<boolean> {
|
|
37
54
|
try {
|
|
38
55
|
// Read pending signals from SQLite (dynamic import to reduce hook startup cost)
|
|
@@ -42,48 +59,25 @@ export async function maybeSpawnReactiveOrchestrate(
|
|
|
42
59
|
const pending = queryImprovementSignals(db, false);
|
|
43
60
|
if (pending.length === 0) return false;
|
|
44
61
|
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
fd = openSync(lockPath, "wx");
|
|
49
|
-
writeFileSync(fd, JSON.stringify({ timestamp: new Date().toISOString(), pid: process.pid }));
|
|
50
|
-
closeSync(fd);
|
|
51
|
-
} catch (lockErr: unknown) {
|
|
52
|
-
// Lock exists — check if stale
|
|
53
|
-
if ((lockErr as NodeJS.ErrnoException).code === "EEXIST") {
|
|
54
|
-
try {
|
|
55
|
-
const lockContent = readFileSync(lockPath, "utf8");
|
|
56
|
-
const lock = JSON.parse(lockContent);
|
|
57
|
-
const lockAge = Date.now() - new Date(lock.timestamp).getTime();
|
|
58
|
-
if (lockAge < LOCK_STALE_MS) return false; // Active lock, skip
|
|
59
|
-
// Stale lock — override
|
|
60
|
-
writeFileSync(
|
|
61
|
-
lockPath,
|
|
62
|
-
JSON.stringify({ timestamp: new Date().toISOString(), pid: process.pid }),
|
|
63
|
-
);
|
|
64
|
-
} catch {
|
|
65
|
-
return false; // Can't read lock, skip
|
|
66
|
-
}
|
|
67
|
-
} else {
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
62
|
+
// Do not pre-claim the orchestrate lock here. The spawned process must
|
|
63
|
+
// acquire its own lock or it will immediately self-block on startup.
|
|
64
|
+
if (hasFreshOrchestrateLock(lockPath)) return false;
|
|
71
65
|
|
|
72
66
|
// Spawn orchestrate in background (fire-and-forget)
|
|
73
67
|
try {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
const spawnOrchestrate =
|
|
69
|
+
deps.spawnOrchestrate ??
|
|
70
|
+
(() => {
|
|
71
|
+
const proc = Bun.spawn(["selftune", "orchestrate", "--max-skills", "2"], {
|
|
72
|
+
stdout: "ignore",
|
|
73
|
+
stderr: "ignore",
|
|
74
|
+
stdin: "ignore",
|
|
75
|
+
});
|
|
76
|
+
proc.unref();
|
|
77
|
+
return true;
|
|
78
|
+
});
|
|
79
|
+
if (!spawnOrchestrate()) return false;
|
|
80
80
|
} catch {
|
|
81
|
-
// Spawn failed — release our lock
|
|
82
|
-
try {
|
|
83
|
-
unlinkSync(lockPath);
|
|
84
|
-
} catch {
|
|
85
|
-
/* ignore */
|
|
86
|
-
}
|
|
87
81
|
return false;
|
|
88
82
|
}
|
|
89
83
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import { existsSync, readFileSync } from "node:fs";
|
|
15
15
|
import { basename, dirname } from "node:path";
|
|
16
|
+
|
|
16
17
|
import { CANONICAL_LOG, SKILL_LOG } from "../constants.js";
|
|
17
18
|
import {
|
|
18
19
|
appendCanonicalRecord,
|
|
@@ -24,7 +25,6 @@ import {
|
|
|
24
25
|
getLatestPromptIdentity,
|
|
25
26
|
} from "../normalization.js";
|
|
26
27
|
import type { PostToolUsePayload, SkillUsageRecord } from "../types.js";
|
|
27
|
-
|
|
28
28
|
import { classifySkillPath } from "../utils/skill-discovery.js";
|
|
29
29
|
import { getLastUserMessage } from "../utils/transcript.js";
|
|
30
30
|
|
package/cli/selftune/index.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* selftune sync — Sync source-truth telemetry across supported agents
|
|
11
11
|
* selftune orchestrate — Run autonomous core loop (sync → status → evolve → watch)
|
|
12
12
|
* selftune init — Initialize agent identity and config
|
|
13
|
+
* selftune uninstall — Clean removal of all selftune data and config
|
|
13
14
|
* selftune status — Show skill health summary
|
|
14
15
|
* selftune watch — Monitor post-deploy skill health
|
|
15
16
|
* selftune doctor — Run health checks
|
|
@@ -44,6 +45,7 @@ Commands:
|
|
|
44
45
|
sync Sync source-truth telemetry across supported agents
|
|
45
46
|
orchestrate Run autonomous core loop (sync → status → evolve → watch)
|
|
46
47
|
init Initialize agent identity and config
|
|
48
|
+
uninstall Clean removal of all selftune data and config
|
|
47
49
|
status Show skill health summary
|
|
48
50
|
watch Monitor post-deploy skill health
|
|
49
51
|
doctor Run health checks
|
|
@@ -338,6 +340,11 @@ Run 'selftune eval <action> --help' for action-specific options.`);
|
|
|
338
340
|
await cliMain();
|
|
339
341
|
break;
|
|
340
342
|
}
|
|
343
|
+
case "uninstall": {
|
|
344
|
+
const { cliMain } = await import("./uninstall.js");
|
|
345
|
+
await cliMain();
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
341
348
|
case "contribute": {
|
|
342
349
|
const { cliMain } = await import("./contribute/contribute.js");
|
|
343
350
|
await cliMain();
|
|
@@ -464,7 +471,7 @@ Run 'selftune cron <subcommand> --help' for subcommand-specific options.`);
|
|
|
464
471
|
}
|
|
465
472
|
case "sync": {
|
|
466
473
|
const { cliMain } = await import("./sync.js");
|
|
467
|
-
cliMain();
|
|
474
|
+
await cliMain();
|
|
468
475
|
break;
|
|
469
476
|
}
|
|
470
477
|
case "workflows": {
|
|
@@ -606,9 +613,8 @@ Output:
|
|
|
606
613
|
const { readAlphaIdentity } = await import("./alpha-identity.js");
|
|
607
614
|
const { getDb } = await import("./localdb/db.js");
|
|
608
615
|
const { runUploadCycle } = await import("./alpha-upload/index.js");
|
|
609
|
-
const { getSelftuneVersion, readConfiguredAgentType } =
|
|
610
|
-
"./utils/selftune-meta.js"
|
|
611
|
-
);
|
|
616
|
+
const { getSelftuneVersion, readConfiguredAgentType } =
|
|
617
|
+
await import("./utils/selftune-meta.js");
|
|
612
618
|
|
|
613
619
|
const identity = readAlphaIdentity(SELFTUNE_CONFIG_PATH);
|
|
614
620
|
if (!identity?.enrolled) {
|
|
@@ -670,36 +676,39 @@ Output:
|
|
|
670
676
|
}
|
|
671
677
|
case "relink": {
|
|
672
678
|
const { SELFTUNE_CONFIG_PATH } = await import("./constants.js");
|
|
673
|
-
const { readAlphaIdentity, writeAlphaIdentity, generateUserId } =
|
|
674
|
-
"./alpha-identity.js"
|
|
675
|
-
|
|
676
|
-
|
|
679
|
+
const { readAlphaIdentity, writeAlphaIdentity, generateUserId } =
|
|
680
|
+
await import("./alpha-identity.js");
|
|
681
|
+
const { buildVerificationUrl, pollDeviceCode, requestDeviceCode, tryOpenUrl } =
|
|
682
|
+
await import("./auth/device-code.js");
|
|
677
683
|
const { chmodSync } = await import("node:fs");
|
|
678
684
|
|
|
679
685
|
const existingIdentity = readAlphaIdentity(SELFTUNE_CONFIG_PATH);
|
|
680
686
|
process.stderr.write("[alpha relink] Starting device-code authentication flow...\n");
|
|
681
687
|
|
|
682
688
|
const grant = await requestDeviceCode();
|
|
689
|
+
const verificationUrlWithCode = buildVerificationUrl(
|
|
690
|
+
grant.verification_url,
|
|
691
|
+
grant.user_code,
|
|
692
|
+
);
|
|
683
693
|
|
|
684
694
|
console.log(
|
|
685
695
|
JSON.stringify({
|
|
686
696
|
level: "info",
|
|
687
697
|
code: "device_code_issued",
|
|
688
698
|
verification_url: grant.verification_url,
|
|
699
|
+
verification_url_with_code: verificationUrlWithCode,
|
|
689
700
|
user_code: grant.user_code,
|
|
690
701
|
expires_in: grant.expires_in,
|
|
691
|
-
message: `Open ${
|
|
702
|
+
message: `Open ${verificationUrlWithCode} to approve.`,
|
|
692
703
|
}),
|
|
693
704
|
);
|
|
694
705
|
|
|
695
706
|
// Try to open browser
|
|
696
|
-
|
|
697
|
-
const url = `${grant.verification_url}?code=${grant.user_code}`;
|
|
698
|
-
Bun.spawn(["open", url], { stdout: "ignore", stderr: "ignore" });
|
|
707
|
+
if (tryOpenUrl(verificationUrlWithCode)) {
|
|
699
708
|
process.stderr.write("[alpha relink] Browser opened. Waiting for approval...\n");
|
|
700
|
-
}
|
|
709
|
+
} else {
|
|
701
710
|
process.stderr.write(
|
|
702
|
-
|
|
711
|
+
`[alpha relink] Could not open browser. Visit ${verificationUrlWithCode} manually.\n`,
|
|
703
712
|
);
|
|
704
713
|
}
|
|
705
714
|
|
|
@@ -25,6 +25,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
|
25
25
|
import { homedir } from "node:os";
|
|
26
26
|
import { basename, join } from "node:path";
|
|
27
27
|
import { parseArgs } from "node:util";
|
|
28
|
+
|
|
28
29
|
import { CANONICAL_LOG, QUERY_LOG, SKILL_LOG, TELEMETRY_LOG } from "../constants.js";
|
|
29
30
|
import {
|
|
30
31
|
appendCanonicalRecords,
|
|
@@ -25,6 +25,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
|
25
25
|
import { homedir } from "node:os";
|
|
26
26
|
import { basename, join } from "node:path";
|
|
27
27
|
import { parseArgs } from "node:util";
|
|
28
|
+
|
|
28
29
|
import { CANONICAL_LOG, QUERY_LOG, SKILL_LOG, TELEMETRY_LOG } from "../constants.js";
|
|
29
30
|
import {
|
|
30
31
|
appendCanonicalRecords,
|