@sunasteriskrnd/takumi 1.0.0-dev.1 → 1.0.0-dev.2

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.
Files changed (3) hide show
  1. package/README.md +6 -0
  2. package/dist/index.js +355 -187
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -33,12 +33,18 @@ Verify: `tkm --version`
33
33
 
34
34
  ```bash
35
35
  tkm --help # All commands
36
+ tkm auth login # One-time login (default install path)
36
37
  tkm new # Create new project (interactive)
37
38
  tkm new --kit engineer # Create with specific kit
38
39
  tkm init # Initialize/update in current project
39
40
  tkm init -g -y # Global install, non-interactive
40
41
  ```
41
42
 
43
+ The default `tkm init` / `new` / `versions` flows download releases
44
+ through the authenticated Takumi server (no `gh` CLI required). Run
45
+ `tkm auth login` once before the first install. The legacy GitHub
46
+ flow is still available via `--use-gh` for archived tags.
47
+
42
48
  ### Create New Project
43
49
 
44
50
  ```bash
package/dist/index.js CHANGED
@@ -11361,7 +11361,8 @@ var init_commands = __esm(() => {
11361
11361
  VersionCommandOptionsSchema = exports_external.object({
11362
11362
  kit: KitType.optional(),
11363
11363
  limit: exports_external.number().optional(),
11364
- all: exports_external.boolean().optional()
11364
+ all: exports_external.boolean().optional(),
11365
+ useGh: exports_external.boolean().default(false)
11365
11366
  }).merge(GlobalOutputOptionsSchema);
11366
11367
  UninstallCommandOptionsSchema = exports_external.object({
11367
11368
  yes: exports_external.boolean().default(false),
@@ -40841,6 +40842,49 @@ var init_agents_command_help = __esm(() => {
40841
40842
  };
40842
40843
  });
40843
40844
 
40845
+ // src/domains/help/commands/auth-command-help.ts
40846
+ var authCommandHelp;
40847
+ var init_auth_command_help = __esm(() => {
40848
+ authCommandHelp = {
40849
+ name: "auth",
40850
+ description: "Sign in/out and check Takumi session (login|logout|status)",
40851
+ usage: "tkm auth <login|logout|status>",
40852
+ examples: [
40853
+ {
40854
+ command: "tkm auth login",
40855
+ description: "Sign in via browser (Supabase OAuth, PKCE-localhost flow)"
40856
+ },
40857
+ {
40858
+ command: "tkm auth status",
40859
+ description: "Show signed-in identity and token expiry"
40860
+ },
40861
+ {
40862
+ command: "tkm auth logout",
40863
+ description: "Clear local Takumi session"
40864
+ }
40865
+ ],
40866
+ optionGroups: [
40867
+ {
40868
+ title: "Actions",
40869
+ options: [
40870
+ {
40871
+ flags: "login",
40872
+ description: "Open browser, complete PKCE-localhost flow, store session"
40873
+ },
40874
+ {
40875
+ flags: "status",
40876
+ description: "Print signed-in email and token expiry; refreshes if needed"
40877
+ },
40878
+ {
40879
+ flags: "logout",
40880
+ description: "Remove the local session token"
40881
+ }
40882
+ ]
40883
+ }
40884
+ ]
40885
+ };
40886
+ });
40887
+
40844
40888
  // src/domains/help/commands/commands-command-help.ts
40845
40889
  var commandsCommandHelp;
40846
40890
  var init_commands_command_help = __esm(() => {
@@ -41153,6 +41197,7 @@ var init_commands2 = __esm(() => {
41153
41197
  init_projects_command_help();
41154
41198
  init_setup_command_help();
41155
41199
  init_agents_command_help();
41200
+ init_auth_command_help();
41156
41201
  init_commands_command_help();
41157
41202
  init_content_command_help();
41158
41203
  init_migrate_command_help();
@@ -41181,6 +41226,7 @@ var init_help_commands = __esm(() => {
41181
41226
  uninstall: uninstallCommandHelp,
41182
41227
  skills: skillsCommandHelp,
41183
41228
  agents: agentsCommandHelp,
41229
+ auth: authCommandHelp,
41184
41230
  commands: commandsCommandHelp,
41185
41231
  migrate: migrateCommandHelp,
41186
41232
  watch: watchCommandHelp
@@ -53916,9 +53962,119 @@ async function doctorCommand(options2 = {}) {
53916
53962
  }
53917
53963
 
53918
53964
  // src/domains/sync/config-version-checker.ts
53965
+ init_auth_client();
53919
53966
  import { mkdir as mkdir10, readFile as readFile16, unlink as unlink9, writeFile as writeFile14 } from "node:fs/promises";
53920
53967
  import { join as join34 } from "node:path";
53921
53968
 
53969
+ // src/domains/installation/release-source.ts
53970
+ init_auth_client();
53971
+
53972
+ // src/types/release-entry.ts
53973
+ init_zod();
53974
+ var ReleaseEntrySchema = exports_external.object({
53975
+ tag: exports_external.string(),
53976
+ version: exports_external.string(),
53977
+ prerelease: exports_external.boolean(),
53978
+ published_at: exports_external.string(),
53979
+ archive: exports_external.string()
53980
+ }).transform((raw) => ({
53981
+ tag: raw.tag,
53982
+ version: raw.version,
53983
+ prerelease: raw.prerelease,
53984
+ publishedAt: raw.published_at,
53985
+ archive: raw.archive
53986
+ }));
53987
+ var ReleaseListResponseSchema = exports_external.object({
53988
+ channel: exports_external.enum(["stable", "beta"]),
53989
+ updated_at: exports_external.string().nullable().optional(),
53990
+ versions: exports_external.array(ReleaseEntrySchema)
53991
+ });
53992
+
53993
+ class NotInIndexError extends Error {
53994
+ tag;
53995
+ constructor(tag) {
53996
+ super(`Tag ${tag} not in Worker index. For archived versions use --use-gh.`);
53997
+ this.name = "NotInIndexError";
53998
+ this.tag = tag;
53999
+ }
54000
+ }
54001
+
54002
+ // src/domains/installation/release-source.ts
54003
+ function assetNameFor(kit) {
54004
+ return `takumi-${kit}-package.zip`;
54005
+ }
54006
+
54007
+ class WorkerSource {
54008
+ serverUrl;
54009
+ kit;
54010
+ tokenProvider;
54011
+ kind = "worker";
54012
+ constructor(serverUrl, kit = "engineer", tokenProvider = getValidToken) {
54013
+ this.serverUrl = serverUrl;
54014
+ this.kit = kit;
54015
+ this.tokenProvider = tokenProvider;
54016
+ }
54017
+ async authHeaders() {
54018
+ const token = await this.tokenProvider();
54019
+ if (!token)
54020
+ throw new NotLoggedInError;
54021
+ return {
54022
+ Authorization: `Bearer ${token}`,
54023
+ "X-TKM-Client": "takumi-cli/release-source"
54024
+ };
54025
+ }
54026
+ async fetchLatest(beta) {
54027
+ const url = `${this.serverUrl}/api/packages/${encodeURIComponent(this.kit)}/releases/latest${beta ? "?beta=1" : ""}`;
54028
+ const headers = await this.authHeaders();
54029
+ const res = await fetch(url, { headers });
54030
+ if (res.status === 401)
54031
+ throw new NotLoggedInError;
54032
+ if (!res.ok) {
54033
+ throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
54034
+ }
54035
+ return ReleaseEntrySchema.parse(await res.json());
54036
+ }
54037
+ async fetchReleaseList(beta) {
54038
+ const url = `${this.serverUrl}/api/packages/${encodeURIComponent(this.kit)}/releases${beta ? "?beta=1" : ""}`;
54039
+ const headers = await this.authHeaders();
54040
+ const res = await fetch(url, { headers });
54041
+ if (res.status === 401)
54042
+ throw new NotLoggedInError;
54043
+ if (!res.ok) {
54044
+ throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
54045
+ }
54046
+ const parsed = ReleaseListResponseSchema.parse(await res.json());
54047
+ return parsed.versions;
54048
+ }
54049
+ async fetchByTag(tag) {
54050
+ const url = `${this.serverUrl}/api/packages/${encodeURIComponent(this.kit)}/releases/${encodeURIComponent(tag)}`;
54051
+ const headers = await this.authHeaders();
54052
+ const res = await fetch(url, { headers });
54053
+ if (res.status === 401)
54054
+ throw new NotLoggedInError;
54055
+ if (res.status === 404)
54056
+ throw new NotInIndexError(tag);
54057
+ if (!res.ok) {
54058
+ throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
54059
+ }
54060
+ return ReleaseEntrySchema.parse(await res.json());
54061
+ }
54062
+ async fetchAsset(tag, asset) {
54063
+ const url = `${this.serverUrl}/api/packages/${encodeURIComponent(this.kit)}/releases/${encodeURIComponent(tag)}/${encodeURIComponent(asset)}`;
54064
+ const headers = await this.authHeaders();
54065
+ const res = await fetch(url, { headers });
54066
+ if (res.status === 401)
54067
+ throw new NotLoggedInError;
54068
+ if (res.status === 404) {
54069
+ throw new Error(`Asset not found: ${this.kit}/${tag}/${asset}`);
54070
+ }
54071
+ if (!res.ok) {
54072
+ throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
54073
+ }
54074
+ return res;
54075
+ }
54076
+ }
54077
+
53922
54078
  // src/domains/versioning/checking/version-utils.ts
53923
54079
  var import_compare_versions2 = __toESM(require_umd(), 1);
53924
54080
  function isUpdateCheckDisabled() {
@@ -53968,7 +54124,6 @@ function isNewerVersion(currentVersion, latestVersion) {
53968
54124
  // src/domains/sync/config-version-checker.ts
53969
54125
  init_logger();
53970
54126
  init_path_resolver();
53971
- init_takumi_constants();
53972
54127
  var CACHE_TTL_HOURS = 24;
53973
54128
  var DEFAULT_CACHE_TTL_MS = CACHE_TTL_HOURS * 60 * 60 * 1000;
53974
54129
  var MIN_CACHE_TTL_MS = 60 * 1000;
@@ -53995,11 +54150,7 @@ function parseCacheTtl() {
53995
54150
  return ttlMs;
53996
54151
  }
53997
54152
  var CACHE_TTL_MS = parseCacheTtl();
53998
- var GITHUB_API_TIMEOUT_MS = 1e4;
53999
54153
  var CACHE_FILENAME = "config-update-cache.json";
54000
- var KIT_REPOS = {
54001
- engineer: { owner: "sun-asterisk-internal", repo: "agent-kit" }
54002
- };
54003
54154
 
54004
54155
  class ConfigVersionChecker {
54005
54156
  static getCacheFilePath(kitType, global3) {
@@ -54030,61 +54181,30 @@ class ConfigVersionChecker {
54030
54181
  logger.debug(`Cache write failed: ${error instanceof Error ? error.message : "Unknown error"}`);
54031
54182
  }
54032
54183
  }
54033
- static async fetchLatestVersion(kitType, etag) {
54034
- const repoInfo = KIT_REPOS[kitType];
54035
- if (!repoInfo)
54036
- return null;
54037
- const url = `https://api.github.com/repos/${repoInfo.owner}/${repoInfo.repo}/releases/latest`;
54184
+ static async fetchLatestVersion(kitType) {
54038
54185
  const maxRetries = 3;
54039
54186
  const baseBackoff = 1000;
54040
54187
  for (let attempt = 0;attempt < maxRetries; attempt++) {
54041
54188
  try {
54042
- const headers = {
54043
- Accept: "application/vnd.github.v3+json",
54044
- "User-Agent": getCliUserAgent()
54045
- };
54046
- const githubToken = process.env.GITHUB_TOKEN;
54047
- if (githubToken) {
54048
- headers.Authorization = `Bearer ${githubToken}`;
54049
- }
54050
- if (etag) {
54051
- headers["If-None-Match"] = etag;
54052
- }
54053
- const response = await fetch(url, {
54054
- headers,
54055
- signal: AbortSignal.timeout(GITHUB_API_TIMEOUT_MS)
54056
- });
54057
- const remaining = response.headers.get("x-ratelimit-remaining");
54058
- if (remaining && Number.parseInt(remaining, 10) < 10) {
54059
- logger.warning(`GitHub API rate limit low: ${remaining} remaining. Set GITHUB_TOKEN env var for higher limits (5000/hr vs 60/hr).`);
54060
- }
54061
- if (response.status === 304) {
54062
- return "not-modified";
54063
- }
54064
- if (!response.ok) {
54065
- if (response.status === 403) {
54066
- logger.warning("GitHub API rate limit exceeded. " + "Set GITHUB_TOKEN env var for higher limits (5000/hr vs 60/hr).");
54067
- return null;
54068
- }
54069
- throw new Error(`GitHub API returned ${response.status}`);
54070
- }
54071
- const data = await response.json();
54072
- const version3 = data.tag_name?.replace(/^v/, "") || null;
54189
+ const worker = new WorkerSource(getServerUrl(), kitType);
54190
+ const entry = await worker.fetchLatest();
54191
+ const version3 = entry.version.replace(/^v/, "");
54073
54192
  if (!version3 || version3.length > 256) {
54074
- logger.debug(`Invalid version format from GitHub: ${data.tag_name}`);
54193
+ logger.debug(`Invalid version format from Worker: ${entry.version}`);
54075
54194
  return null;
54076
54195
  }
54077
54196
  const semverParts = version3.split(/[-+]/);
54078
54197
  const coreParts = semverParts[0].split(".");
54079
54198
  if (coreParts.length !== 3 || !coreParts.every((p) => /^\d+$/.test(p))) {
54080
- logger.debug(`Invalid version format from GitHub: ${data.tag_name}`);
54199
+ logger.debug(`Invalid version format from Worker: ${entry.version}`);
54081
54200
  return null;
54082
54201
  }
54083
- return {
54084
- version: version3,
54085
- etag: response.headers.get("etag") || undefined
54086
- };
54202
+ return { version: version3 };
54087
54203
  } catch (error) {
54204
+ if (error instanceof NotLoggedInError) {
54205
+ logger.debug("Skipping update check (not logged in)");
54206
+ return null;
54207
+ }
54088
54208
  const isLastAttempt = attempt === maxRetries - 1;
54089
54209
  if (isLastAttempt) {
54090
54210
  logger.debug(`Version check failed after ${maxRetries} attempts: ${error}`);
@@ -54109,25 +54229,11 @@ class ConfigVersionChecker {
54109
54229
  fromCache: true
54110
54230
  };
54111
54231
  }
54112
- const result = await ConfigVersionChecker.fetchLatestVersion(kitType, cache?.etag);
54113
- if (result === "not-modified" && cache) {
54114
- await ConfigVersionChecker.saveCache(kitType, global3, {
54115
- ...cache,
54116
- lastCheck: now
54117
- });
54118
- const hasUpdates = isNewerVersion(normalizedCurrent, cache.latestVersion);
54119
- return {
54120
- hasUpdates,
54121
- currentVersion: normalizedCurrent,
54122
- latestVersion: cache.latestVersion,
54123
- fromCache: false
54124
- };
54125
- }
54126
- if (result && result !== "not-modified") {
54232
+ const result = await ConfigVersionChecker.fetchLatestVersion(kitType);
54233
+ if (result) {
54127
54234
  await ConfigVersionChecker.saveCache(kitType, global3, {
54128
54235
  lastCheck: now,
54129
- latestVersion: result.version,
54130
- etag: result.etag
54236
+ latestVersion: result.version
54131
54237
  });
54132
54238
  const hasUpdates = isNewerVersion(normalizedCurrent, result.version);
54133
54239
  return {
@@ -56222,7 +56328,38 @@ async function getDirectory(defaultDir = ".") {
56222
56328
  return trimmed.length > 0 ? trimmed : defaultDir;
56223
56329
  }
56224
56330
  // src/domains/versioning/version-selector.ts
56331
+ init_auth_client();
56225
56332
  init_github_client();
56333
+
56334
+ // src/domains/installation/release-entry-adapter.ts
56335
+ function githubReleaseToEntry(release, kit = "engineer") {
56336
+ const expected = assetNameFor(kit);
56337
+ const expectedAsset = release.assets.find((a3) => a3.name === expected);
56338
+ const fallback2 = release.assets[0];
56339
+ const archive = expectedAsset?.name ?? fallback2?.name ?? expected;
56340
+ return {
56341
+ tag: release.tag_name,
56342
+ version: release.tag_name.replace(/^v/, ""),
56343
+ prerelease: release.prerelease,
56344
+ publishedAt: release.published_at ?? "",
56345
+ archive
56346
+ };
56347
+ }
56348
+ function releaseEntryToGitHubRelease(entry, kit) {
56349
+ return {
56350
+ id: 0,
56351
+ tag_name: entry.tag,
56352
+ name: entry.tag,
56353
+ draft: false,
56354
+ prerelease: entry.prerelease,
56355
+ published_at: entry.publishedAt || undefined,
56356
+ tarball_url: `https://github.com/${kit.owner}/${kit.repo}/archive/refs/tags/${entry.tag}.tar.gz`,
56357
+ zipball_url: `https://github.com/${kit.owner}/${kit.repo}/archive/refs/tags/${entry.tag}.zip`,
56358
+ assets: []
56359
+ };
56360
+ }
56361
+
56362
+ // src/domains/versioning/version-selector.ts
56226
56363
  init_logger();
56227
56364
  init_dist2();
56228
56365
  init_release_filter();
@@ -56553,6 +56690,17 @@ class VersionSelector {
56553
56690
  constructor(githubClient) {
56554
56691
  this.githubClient = githubClient ?? new GitHubClient;
56555
56692
  }
56693
+ async fetchFromWorker(kit, includePrereleases) {
56694
+ const worker = new WorkerSource(getServerUrl(), kit.id);
56695
+ const entries = await worker.fetchReleaseList(includePrereleases);
56696
+ const releases = entries.map((entry, idx) => ({
56697
+ ...releaseEntryToGitHubRelease(entry, kit),
56698
+ id: entries.length - idx
56699
+ }));
56700
+ return ReleaseFilter.processReleases(releases, {
56701
+ includePrereleases
56702
+ });
56703
+ }
56556
56704
  async selectVersion(options2) {
56557
56705
  const {
56558
56706
  kit,
@@ -56561,18 +56709,24 @@ class VersionSelector {
56561
56709
  defaultValue,
56562
56710
  allowManualEntry = false,
56563
56711
  forceRefresh = false,
56564
- currentVersion = null
56712
+ currentVersion = null,
56713
+ useGh = false
56565
56714
  } = options2;
56566
56715
  try {
56567
56716
  const loadingSpinner = de();
56568
56717
  loadingSpinner.start(`Fetching versions for ${import_picocolors18.default.bold(kit.name)}...`);
56569
- let releases = await this.githubClient.listReleasesWithCache(kit, {
56570
- limit: limit * 2,
56571
- includePrereleases,
56572
- forceRefresh
56573
- });
56574
- if (includePrereleases) {
56575
- releases = await this.injectLatestStable(kit, releases, forceRefresh);
56718
+ let releases;
56719
+ if (useGh) {
56720
+ releases = await this.githubClient.listReleasesWithCache(kit, {
56721
+ limit: limit * 2,
56722
+ includePrereleases,
56723
+ forceRefresh
56724
+ });
56725
+ if (includePrereleases) {
56726
+ releases = await this.injectLatestStable(kit, releases, forceRefresh);
56727
+ }
56728
+ } else {
56729
+ releases = await this.fetchFromWorker(kit, includePrereleases);
56576
56730
  }
56577
56731
  loadingSpinner.stop();
56578
56732
  if (releases.length === 0) {
@@ -56604,17 +56758,19 @@ class VersionSelector {
56604
56758
  return releases;
56605
56759
  }
56606
56760
  }
56607
- async getLatestVersion(kit, includePrereleases = false, forceRefresh = false) {
56761
+ async getLatestVersion(kit, includePrereleases = false, forceRefresh = false, useGh = false) {
56608
56762
  try {
56609
- const releases = await this.githubClient.listReleasesWithCache(kit, {
56610
- limit: 5,
56611
- includePrereleases,
56612
- forceRefresh
56613
- });
56614
- if (releases.length === 0) {
56615
- return null;
56763
+ if (useGh) {
56764
+ const releases = await this.githubClient.listReleasesWithCache(kit, {
56765
+ limit: 5,
56766
+ includePrereleases,
56767
+ forceRefresh
56768
+ });
56769
+ return releases[0]?.tag_name ?? null;
56616
56770
  }
56617
- return releases[0].tag_name;
56771
+ const worker = new WorkerSource(getServerUrl(), kit.id);
56772
+ const entry = await worker.fetchLatest(includePrereleases);
56773
+ return entry.tag;
56618
56774
  } catch (error) {
56619
56775
  logger.error(`Failed to get latest version for ${kit.name}: ${error}`);
56620
56776
  return null;
@@ -61162,58 +61318,6 @@ Solutions:
61162
61318
  }
61163
61319
  }
61164
61320
 
61165
- // src/domains/installation/release-source.ts
61166
- init_auth_client();
61167
- function assetNameFor(kit) {
61168
- return `takumi-${kit}-package.zip`;
61169
- }
61170
-
61171
- class WorkerSource {
61172
- serverUrl;
61173
- kit;
61174
- tokenProvider;
61175
- kind = "worker";
61176
- constructor(serverUrl, kit = "engineer", tokenProvider = getValidToken) {
61177
- this.serverUrl = serverUrl;
61178
- this.kit = kit;
61179
- this.tokenProvider = tokenProvider;
61180
- }
61181
- async authHeaders() {
61182
- const token = await this.tokenProvider();
61183
- if (!token)
61184
- throw new NotLoggedInError;
61185
- return {
61186
- Authorization: `Bearer ${token}`,
61187
- "X-TKM-Client": "takumi-cli/release-source"
61188
- };
61189
- }
61190
- async fetchLatest() {
61191
- const url = `${this.serverUrl}/api/packages/${encodeURIComponent(this.kit)}/releases/latest`;
61192
- const headers = await this.authHeaders();
61193
- const res = await fetch(url, { headers });
61194
- if (res.status === 401)
61195
- throw new NotLoggedInError;
61196
- if (!res.ok) {
61197
- throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
61198
- }
61199
- return await res.json();
61200
- }
61201
- async fetchAsset(tag, asset) {
61202
- const url = `${this.serverUrl}/api/packages/${encodeURIComponent(this.kit)}/releases/${encodeURIComponent(tag)}/${encodeURIComponent(asset)}`;
61203
- const headers = await this.authHeaders();
61204
- const res = await fetch(url, { headers });
61205
- if (res.status === 401)
61206
- throw new NotLoggedInError;
61207
- if (res.status === 404) {
61208
- throw new Error(`Asset not found: ${this.kit}/${tag}/${asset}`);
61209
- }
61210
- if (!res.ok) {
61211
- throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
61212
- }
61213
- return res;
61214
- }
61215
- }
61216
-
61217
61321
  // src/domains/installation/download-extractor.ts
61218
61322
  init_logger();
61219
61323
  init_output_manager();
@@ -68039,6 +68143,7 @@ async function handlePostInstall(ctx) {
68039
68143
  };
68040
68144
  }
68041
68145
  // src/commands/init/phases/selection-handler.ts
68146
+ init_auth_client();
68042
68147
  import { mkdir as mkdir24 } from "node:fs/promises";
68043
68148
  import { join as join81, resolve as resolve13 } from "node:path";
68044
68149
  init_github_client();
@@ -68379,9 +68484,16 @@ async function handleSelection(ctx) {
68379
68484
  return ctx;
68380
68485
  if (isSyncContext(ctx) && ctx.kitType && ctx.resolvedDir && ctx.selectedVersion) {
68381
68486
  const kit2 = AVAILABLE_KITS[ctx.kitType];
68382
- const github2 = new GitHubClient;
68383
68487
  logger.info(`Sync mode: using ${kit2.name} version ${ctx.selectedVersion}`);
68384
- const release2 = await github2.getReleaseByTag(kit2, ctx.selectedVersion);
68488
+ let release2;
68489
+ if (ctx.options.useGh) {
68490
+ const github2 = new GitHubClient;
68491
+ release2 = await github2.getReleaseByTag(kit2, ctx.selectedVersion);
68492
+ } else {
68493
+ const worker = new WorkerSource(getServerUrl(), ctx.kitType);
68494
+ const entry = await worker.fetchByTag(ctx.selectedVersion);
68495
+ release2 = releaseEntryToGitHubRelease(entry, kit2);
68496
+ }
68385
68497
  return {
68386
68498
  ...ctx,
68387
68499
  kit: kit2,
@@ -68404,7 +68516,8 @@ async function handleSelection(ctx) {
68404
68516
  }
68405
68517
  const config = await ConfigManager.get();
68406
68518
  let accessibleKits;
68407
- if (!ctx.options.useGit && !ctx.options.kitPath && !ctx.options.archive) {
68519
+ const useLegacyGh = !!(ctx.options.useGh || ctx.options.useGit);
68520
+ if (useLegacyGh && !ctx.options.kitPath && !ctx.options.archive) {
68408
68521
  const preflight = await runPreflightChecks();
68409
68522
  if (!preflight.success) {
68410
68523
  for (const line of preflight.errorLines) {
@@ -68560,7 +68673,7 @@ async function handleSelection(ctx) {
68560
68673
  }
68561
68674
  }
68562
68675
  const isOfflineMode = !!(ctx.options.kitPath || ctx.options.archive);
68563
- const github = isOfflineMode ? null : new GitHubClient;
68676
+ const github = !isOfflineMode && useLegacyGh ? new GitHubClient : null;
68564
68677
  let selectedVersion = ctx.options.release;
68565
68678
  if (!selectedVersion && ctx.isNonInteractive && !ctx.options.yes && !isOfflineMode) {
68566
68679
  throw new Error("Non-interactive mode requires either: --release <tag> OR --yes (uses latest)");
@@ -68587,7 +68700,8 @@ async function handleSelection(ctx) {
68587
68700
  limit: 10,
68588
68701
  allowManualEntry: true,
68589
68702
  forceRefresh: ctx.options.refresh,
68590
- currentVersion
68703
+ currentVersion,
68704
+ useGh: useLegacyGh
68591
68705
  });
68592
68706
  if (!versionResult) {
68593
68707
  logger.warning("Version selection cancelled by user");
@@ -68634,6 +68748,24 @@ async function handleSelection(ctx) {
68634
68748
  } else {
68635
68749
  logger.success(`Found: ${release.tag_name}`);
68636
68750
  }
68751
+ } else if (selectedVersion) {
68752
+ const worker = new WorkerSource(getServerUrl(), kitType);
68753
+ const entry = await worker.fetchByTag(selectedVersion);
68754
+ release = releaseEntryToGitHubRelease(entry, kit);
68755
+ } else {
68756
+ if (ctx.options.beta) {
68757
+ logger.info("Fetching latest beta release...");
68758
+ } else {
68759
+ logger.info("Fetching latest release...");
68760
+ }
68761
+ const worker = new WorkerSource(getServerUrl(), kitType);
68762
+ const entry = await worker.fetchLatest(ctx.options.beta);
68763
+ release = releaseEntryToGitHubRelease(entry, kit);
68764
+ if (release.prerelease) {
68765
+ logger.success(`Found beta: ${release.tag_name}`);
68766
+ } else {
68767
+ logger.success(`Found: ${release.tag_name}`);
68768
+ }
68637
68769
  }
68638
68770
  if (ctx.options.force && !ctx.options.yes) {
68639
68771
  logger.info("--force has no effect without --yes (the version-match skip only applies in non-interactive mode)");
@@ -72054,6 +72186,7 @@ init_output_manager();
72054
72186
  init_types2();
72055
72187
 
72056
72188
  // src/commands/new/phases/version-selection.ts
72189
+ init_auth_client();
72057
72190
  init_logger();
72058
72191
  async function selectVersion2(kit, options2, isNonInteractive2, prompts, github) {
72059
72192
  if (options2.kitPath || options2.archive) {
@@ -72076,6 +72209,7 @@ async function selectVersion2(kit, options2, isNonInteractive2, prompts, github)
72076
72209
  if (!selectedVersion && isNonInteractive2) {
72077
72210
  throw new Error("Interactive version selection unavailable in non-interactive mode. " + "Either: (1) use --release <tag> flag, or (2) set CI=false to enable interactive mode");
72078
72211
  }
72212
+ const useLegacyGh = !!(options2.useGh || options2.useGit);
72079
72213
  if (!selectedVersion && !isNonInteractive2) {
72080
72214
  logger.info("Fetching available versions...");
72081
72215
  try {
@@ -72084,7 +72218,8 @@ async function selectVersion2(kit, options2, isNonInteractive2, prompts, github)
72084
72218
  includePrereleases: options2.beta,
72085
72219
  limit: 10,
72086
72220
  allowManualEntry: true,
72087
- forceRefresh: options2.refresh
72221
+ forceRefresh: options2.refresh,
72222
+ useGh: useLegacyGh
72088
72223
  });
72089
72224
  if (!versionResult) {
72090
72225
  logger.warning("Version selection cancelled by user");
@@ -72112,19 +72247,40 @@ async function selectVersion2(kit, options2, isNonInteractive2, prompts, github)
72112
72247
  assets: []
72113
72248
  };
72114
72249
  logger.verbose("Using git clone mode with tag", { tag: selectedVersion });
72115
- } else if (selectedVersion) {
72116
- release = await github.getReleaseByTag(kit, selectedVersion);
72117
- } else {
72118
- if (options2.beta) {
72119
- logger.info("Fetching latest beta release...");
72250
+ } else if (options2.useGh && github) {
72251
+ if (selectedVersion) {
72252
+ release = await github.getReleaseByTag(kit, selectedVersion);
72120
72253
  } else {
72121
- logger.info("Fetching latest release...");
72254
+ if (options2.beta) {
72255
+ logger.info("Fetching latest beta release...");
72256
+ } else {
72257
+ logger.info("Fetching latest release...");
72258
+ }
72259
+ release = await github.getLatestRelease(kit, options2.beta);
72260
+ if (release.prerelease) {
72261
+ logger.success(`Found beta: ${release.tag_name}`);
72262
+ } else {
72263
+ logger.success(`Found: ${release.tag_name}`);
72264
+ }
72122
72265
  }
72123
- release = await github.getLatestRelease(kit, options2.beta);
72124
- if (release.prerelease) {
72125
- logger.success(`Found beta: ${release.tag_name}`);
72266
+ } else {
72267
+ const worker = new WorkerSource(getServerUrl(), kit.id);
72268
+ if (selectedVersion) {
72269
+ const entry = await worker.fetchByTag(selectedVersion);
72270
+ release = releaseEntryToGitHubRelease(entry, kit);
72126
72271
  } else {
72127
- logger.success(`Found: ${release.tag_name}`);
72272
+ if (options2.beta) {
72273
+ logger.info("Fetching latest beta release...");
72274
+ } else {
72275
+ logger.info("Fetching latest release...");
72276
+ }
72277
+ const entry = await worker.fetchLatest(options2.beta);
72278
+ release = releaseEntryToGitHubRelease(entry, kit);
72279
+ if (release.prerelease) {
72280
+ logger.success(`Found beta: ${release.tag_name}`);
72281
+ } else {
72282
+ logger.success(`Found: ${release.tag_name}`);
72283
+ }
72128
72284
  }
72129
72285
  }
72130
72286
  return {
@@ -72136,7 +72292,8 @@ async function selectVersion2(kit, options2, isNonInteractive2, prompts, github)
72136
72292
  // src/commands/new/phases/project-creation.ts
72137
72293
  async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2, prompts) {
72138
72294
  const kitConfig = AVAILABLE_KITS[kit];
72139
- const github = new GitHubClient;
72295
+ const useLegacyGh = !!(validOptions.useGh || validOptions.useGit);
72296
+ const github = useLegacyGh ? new GitHubClient : null;
72140
72297
  const versionResult = await selectVersion2(kitConfig, validOptions, isNonInteractive2, prompts, github);
72141
72298
  if (!versionResult) {
72142
72299
  return null;
@@ -73961,11 +74118,9 @@ async function handlePreflightCheck(ctx) {
73961
74118
  f2.step("Running preflight checks...");
73962
74119
  let hasIssues = false;
73963
74120
  if (!isGhInstalled()) {
73964
- f2.warning("GitHub CLI not installed. Install from https://cli.github.com/ then run 'gh auth login'.");
73965
- hasIssues = true;
74121
+ f2.info("GitHub CLI not installed (optional needed only for legacy `--use-gh` / `--use-git` flows).");
73966
74122
  } else if (!checkGhAuth()) {
73967
- f2.warning("GitHub CLI not authenticated. Run 'gh auth login' to authenticate with GitHub.");
73968
- hasIssues = true;
74123
+ f2.info("GitHub CLI not authenticated (optional needed only for legacy `--use-gh` / `--use-git` flows).");
73969
74124
  } else {
73970
74125
  f2.success("GitHub CLI: authenticated");
73971
74126
  }
@@ -75971,7 +76126,7 @@ var import_fs_extra37 = __toESM(require_lib(), 1);
75971
76126
  // package.json
75972
76127
  var package_default = {
75973
76128
  name: "@sunasteriskrnd/takumi",
75974
- version: "1.0.0-dev.1",
76129
+ version: "1.0.0-dev.2",
75975
76130
  description: "CLI tool for bootstrapping and managing Takumi projects",
75976
76131
  type: "module",
75977
76132
  repository: {
@@ -76550,6 +76705,7 @@ Manual update: ${redactCommandForLog(updateCmd)}`;
76550
76705
  }
76551
76706
 
76552
76707
  // src/commands/version.ts
76708
+ init_auth_client();
76553
76709
  init_github_client();
76554
76710
  init_logger();
76555
76711
  init_types2();
@@ -76582,44 +76738,45 @@ ${import_picocolors35.default.bold(import_picocolors35.default.cyan(kitName))} -
76582
76738
  return;
76583
76739
  }
76584
76740
  for (const release of releases) {
76585
- const version3 = import_picocolors35.default.green(release.tag_name);
76586
- const name = release.name || "No title";
76587
- const publishedAt = formatRelativeTime(release.published_at);
76588
- const assetCount = release.assets.length;
76589
- const badges = [];
76590
- if (release.prerelease)
76591
- badges.push(import_picocolors35.default.yellow("[prerelease]"));
76592
- if (release.draft)
76593
- badges.push(import_picocolors35.default.gray("[draft]"));
76594
- const badgeStr = badges.length > 0 ? ` ${badges.join(" ")}` : "";
76741
+ const version3 = import_picocolors35.default.green(release.tag);
76742
+ const publishedAt = formatRelativeTime(release.publishedAt);
76743
+ const badge = release.prerelease ? ` ${import_picocolors35.default.yellow("[prerelease]")}` : "";
76595
76744
  const versionPart = version3.padEnd(20);
76596
- const namePart = name.length > 40 ? `${name.slice(0, 37)}...` : name.padEnd(40);
76597
76745
  const timePart = import_picocolors35.default.dim(publishedAt.padEnd(20));
76598
- const assetPart = import_picocolors35.default.dim(`(${assetCount} ${assetCount === 1 ? "asset" : "assets"})`);
76599
- console.log(` ${versionPart} ${namePart} ${timePart} ${assetPart}${badgeStr}`);
76746
+ console.log(` ${versionPart} ${timePart}${badge}`);
76600
76747
  }
76601
76748
  console.log(import_picocolors35.default.dim(`
76602
76749
  Showing ${releases.length} ${releases.length === 1 ? "release" : "releases"}`));
76603
76750
  }
76751
+ async function fetchReleasesForKit(kitType, options2) {
76752
+ const kitConfig = AVAILABLE_KITS[kitType];
76753
+ if (options2.useGh) {
76754
+ const github = new GitHubClient;
76755
+ const releases = await github.listReleases(kitConfig, options2.limit);
76756
+ const filtered = options2.includePrereleases ? releases : releases.filter((r2) => !r2.draft && !r2.prerelease);
76757
+ return filtered.map((r2) => githubReleaseToEntry(r2, kitType));
76758
+ }
76759
+ const worker = new WorkerSource(getServerUrl(), kitType);
76760
+ const entries = await worker.fetchReleaseList(options2.includePrereleases);
76761
+ return entries.slice(0, options2.limit);
76762
+ }
76604
76763
  async function versionCommand(options2) {
76605
76764
  const prompts2 = new PromptsManager;
76606
76765
  prompts2.intro("\uD83D\uDCE6 Takumi - Available Versions");
76607
76766
  try {
76608
76767
  const validOptions = VersionCommandOptionsSchema.parse(options2);
76609
76768
  const kitsToFetch = validOptions.kit ? [validOptions.kit] : Object.keys(AVAILABLE_KITS);
76610
- const github = new GitHubClient;
76611
76769
  const limit = validOptions.limit || 30;
76770
+ const includePrereleases = !!validOptions.all;
76612
76771
  const releasePromises = kitsToFetch.map(async (kitType) => {
76613
76772
  const kitConfig = AVAILABLE_KITS[kitType];
76614
76773
  try {
76615
- const releases = await github.listReleases(kitConfig, limit);
76616
- const filteredReleases = validOptions.all ? releases : releases.filter((r2) => !r2.draft && !r2.prerelease);
76617
- return {
76618
- kitType,
76619
- kitConfig,
76620
- releases: filteredReleases,
76621
- error: null
76622
- };
76774
+ const releases = await fetchReleasesForKit(kitType, {
76775
+ includePrereleases,
76776
+ limit,
76777
+ useGh: validOptions.useGh
76778
+ });
76779
+ return { kitType, kitConfig, releases, error: null };
76623
76780
  } catch (error) {
76624
76781
  return {
76625
76782
  kitType,
@@ -78534,7 +78691,7 @@ function registerCommands(cli) {
78534
78691
  process.exit(1);
78535
78692
  }
78536
78693
  });
78537
- cli.command("versions", "List available versions of Takumi repositories").option("--kit <kit>", "Filter by specific kit (engineer)").option("--limit <limit>", "Number of releases to show (default: 30)").option("--all", "Show all releases including prereleases").action(async (options2) => {
78694
+ cli.command("versions", "List available versions of Takumi repositories").option("--kit <kit>", "Filter by specific kit (engineer)").option("--limit <limit>", "Number of releases to show (default: 30)").option("--all", "Show the beta channel (prereleases only) instead of the stable channel. " + "On --use-gh, returns all release types interleaved.").option("--use-gh", "Use legacy GitHub release source (requires gh CLI)").action(async (options2) => {
78538
78695
  await versionCommand(options2);
78539
78696
  });
78540
78697
  cli.command("doctor", "Comprehensive health check for Takumi").option("--report", "Generate shareable diagnostic report").option("--fix", "Auto-fix all fixable issues").option("--check-only", "CI mode: no prompts, exit 1 on failures").option("--json", "Output JSON format").option("--full", "Include extended priority checks (slower)").action(async (options2) => {
@@ -78623,14 +78780,25 @@ function registerCommands(cli) {
78623
78780
  }
78624
78781
  await migrateCommand(options2);
78625
78782
  });
78626
- cli.command("auth login", "Sign in to Takumi via browser (Supabase OAuth)").action(async () => {
78627
- await login();
78628
- });
78629
- cli.command("auth logout", "Clear local Takumi session").action(async () => {
78630
- await logout();
78631
- });
78632
- cli.command("auth status", "Show signed-in identity and token expiry").action(async () => {
78633
- await status();
78783
+ cli.command("auth [action]", "Sign in/out and check Takumi session (login|logout|status)").action(async (action) => {
78784
+ switch (action) {
78785
+ case "login":
78786
+ await login();
78787
+ break;
78788
+ case "logout":
78789
+ await logout();
78790
+ break;
78791
+ case "status":
78792
+ await status();
78793
+ break;
78794
+ case undefined:
78795
+ console.error("Usage: tkm auth <login|logout|status>");
78796
+ process.exitCode = 1;
78797
+ break;
78798
+ default:
78799
+ console.error(`Unknown auth action: ${action}. Available: login, logout, status`);
78800
+ process.exitCode = 1;
78801
+ }
78634
78802
  });
78635
78803
  cli.command("watch", "Watch GitHub issues and auto-respond with AI analysis").option("--interval <ms>", "Poll interval in milliseconds (default: 30000)").option("--dry-run", "Detect issues without posting responses").option("--force", "Kill existing watch process and start fresh").option("--verbose", "Enable verbose logging").action(async (options2) => {
78636
78804
  await watchCommand(options2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunasteriskrnd/takumi",
3
- "version": "1.0.0-dev.1",
3
+ "version": "1.0.0-dev.2",
4
4
  "description": "CLI tool for bootstrapping and managing Takumi projects",
5
5
  "type": "module",
6
6
  "repository": {