@tdsoft-tech/aikit 0.1.30 → 0.1.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -943,6 +943,11 @@ declare class AntiHallucination {
943
943
  private patternToRegex;
944
944
  }
945
945
 
946
+ /**
947
+ * Non-blocking public API for CLI
948
+ */
949
+ declare function checkForUpdatesAsync(): Promise<void>;
950
+
946
951
  /**
947
952
  * Simple logger with colored output
948
953
  */
@@ -1038,4 +1043,4 @@ declare const paths: {
1038
1043
  */
1039
1044
  declare function getVersion(): string;
1040
1045
 
1041
- export { type AIKitConfig, type Agent, AgentManager, type AgentType, AntiHallucination, BeadsIntegration, type Command, CommandRunner, Config, type Memory, MemoryManager, type Plugin, type PluginEvent, PluginSystem, type Skill, SkillEngine, type Tool, ToolRegistry, getVersion as VERSION, defineTool, loadConfig, logger, paths };
1046
+ export { type AIKitConfig, type Agent, AgentManager, type AgentType, AntiHallucination, BeadsIntegration, type Command, CommandRunner, Config, type Memory, MemoryManager, type Plugin, type PluginEvent, PluginSystem, type Skill, SkillEngine, type Tool, ToolRegistry, getVersion as VERSION, checkForUpdatesAsync, defineTool, loadConfig, logger, paths };
package/dist/index.js CHANGED
@@ -153,6 +153,7 @@ var init_paths = __esm({
153
153
  import { readFileSync } from "fs";
154
154
  import { fileURLToPath as fileURLToPath2 } from "url";
155
155
  import { dirname, join as join2 } from "path";
156
+ import { compare, gt, valid } from "semver";
156
157
  function getVersion() {
157
158
  try {
158
159
  const __filename2 = fileURLToPath2(import.meta.url);
@@ -165,6 +166,9 @@ function getVersion() {
165
166
  return "0.0.0";
166
167
  }
167
168
  }
169
+ function isGreaterThan(v1, v2) {
170
+ return gt(v1, v2);
171
+ }
168
172
  var init_version = __esm({
169
173
  "src/utils/version.ts"() {
170
174
  "use strict";
@@ -3459,14 +3463,14 @@ Total: 2 checkpoints
3459
3463
  init_esm_shims();
3460
3464
  var SESSION_COMMANDS = [
3461
3465
  {
3462
- name: "session:start",
3466
+ name: "session-start",
3463
3467
  description: "Start a new development session",
3464
3468
  category: "session",
3465
- usage: "/session:start [name]",
3469
+ usage: "/session-start [name]",
3466
3470
  examples: [
3467
- "/session:start",
3468
- "/session:start authentication-refactor",
3469
- '/session:start "Add user profile feature"'
3471
+ "/session-start",
3472
+ "/session-start authentication-refactor",
3473
+ '/session-start "Add user profile feature"'
3470
3474
  ],
3471
3475
  content: `Start a new development session to track your work.
3472
3476
 
@@ -3474,47 +3478,70 @@ var SESSION_COMMANDS = [
3474
3478
 
3475
3479
  Session name: $ARGUMENTS
3476
3480
 
3477
- 1. **Create Session:**
3478
- - Generate session ID with timestamp
3479
- - Create session file in .aikit/sessions/
3480
- - Track active session in .current-session
3481
- - Capture initial git state
3481
+ **IMPORTANT - Scope Rules:**
3482
+ - Sessions are scoped to the CURRENT working directory
3483
+ - AIKit will NOT search parent directories for .aikit
3484
+ - If .aikit doesn't exist in current directory, you MUST run 'aikit init' first
3485
+ - Each directory needs its own .aikit if you want separate session tracking
3486
+
3487
+ 1. **Check Current Directory:**
3488
+ - Verify .aikit exists in current directory (process.cwd())
3489
+ - If not, inform user to run 'aikit init' first
3490
+ - DO NOT search parent directories
3482
3491
 
3483
- 2. **Set Goals:**
3492
+ 2. **Create Session:**
3493
+ - Generate session ID with timestamp
3494
+ - Create session file in .aikit/sessions/ (current directory only)
3495
+ - Determine session tracker file:
3496
+ * Try 'tty' command to get terminal identifier
3497
+ * If 'tty' works, use .aikit/sessions/.current-<sanitized_tty>-session
3498
+ (replace '/' with '-' in TTY path)
3499
+ * If 'tty' fails with "not a tty", get parent PID using: ps -o ppid= -p $$
3500
+ Use .aikit/sessions/.current-ppid-<PPID>-session
3501
+ (each Claude Code window has unique PPID)
3502
+ - Write session ID to the tracker file
3503
+ - **Capture initial git state (scoped to current directory):**
3504
+ * First check if .git exists in CURRENT directory (process.cwd())
3505
+ * ONLY capture git state if .git exists in current directory
3506
+ * DO NOT search parent directories for git repo
3507
+ * If no .git in current directory, skip git state capture
3508
+
3509
+ 3. **Set Goals:**
3484
3510
  - Ask user for session goals if not provided
3485
3511
  - Document what you want to accomplish
3486
3512
  - Link to Beads task if active
3487
3513
 
3488
- 3. **Session Started:**
3514
+ 4. **Session Started:**
3489
3515
  - Session ID: YYYY-MM-DD-HHMM[-name]
3490
3516
  - Status: active
3491
3517
  - Ready for updates
3492
3518
 
3493
3519
  ## What Gets Tracked
3494
3520
  - Session start time
3495
- - Git branch and commits
3496
- - Modified files
3521
+ - Git branch and commits (ONLY if .git exists in current directory)
3522
+ - Modified files (ONLY if .git exists in current directory)
3497
3523
  - Progress notes
3498
3524
  - Linked Beads task
3499
3525
 
3500
3526
  ## Session File Location
3501
- .aikit/sessions/YYYY-MM-DD-HHMM[-name].md
3527
+ Current directory: .aikit/sessions/YYYY-MM-DD-HHMM[-name].md
3528
+ (Always relative to process.cwd(), never parent directories)
3502
3529
 
3503
3530
  ## Examples
3504
3531
 
3505
3532
  Start unnamed session:
3506
3533
  \`\`\`
3507
- /session:start
3534
+ /session-start
3508
3535
  \`\`\`
3509
3536
 
3510
3537
  Start with descriptive name:
3511
3538
  \`\`\`
3512
- /session:start auth-refactor
3539
+ /session-start auth-refactor
3513
3540
  \`\`\`
3514
3541
 
3515
3542
  Start with goal:
3516
3543
  \`\`\`
3517
- /session:start "Implement OAuth 2.0"
3544
+ /session-start "Implement OAuth 2.0"
3518
3545
  Goals:
3519
3546
  - Add Google OAuth
3520
3547
  - Add JWT token handling
@@ -3523,18 +3550,18 @@ Goals:
3523
3550
  ## Notes
3524
3551
  - Session files are markdown with frontmatter
3525
3552
  - Sessions persist across AI conversations
3526
- - Use /session:update to add progress notes
3527
- - Use /session:end to close and summarize`
3553
+ - Use /session-update to add progress notes
3554
+ - Use /session-end to close and summarize`
3528
3555
  },
3529
3556
  {
3530
- name: "session:update",
3557
+ name: "session-update",
3531
3558
  description: "Add progress notes to current session",
3532
3559
  category: "session",
3533
- usage: "/session:update [notes]",
3560
+ usage: "/session-update [notes]",
3534
3561
  examples: [
3535
- "/session:update",
3536
- "/session:update Fixed authentication bug",
3537
- '/session:update "Added JWT middleware"'
3562
+ "/session-update",
3563
+ "/session-update Fixed authentication bug",
3564
+ '/session-update "Added JWT middleware"'
3538
3565
  ],
3539
3566
  content: `Update the current session with progress notes.
3540
3567
 
@@ -3543,19 +3570,28 @@ Goals:
3543
3570
  Progress notes: $ARGUMENTS
3544
3571
 
3545
3572
  1. **Check Active Session:**
3546
- - Verify there's an active session
3573
+ - Determine session tracker file:
3574
+ * Try 'tty' command to get terminal identifier
3575
+ * If 'tty' works, read .aikit/sessions/.current-<sanitized_tty>-session
3576
+ * If 'tty' fails, get parent PID and read .aikit/sessions/.current-ppid-<PPID>-session
3547
3577
  - Load session file
3548
3578
 
3549
3579
  2. **Capture Current State:**
3550
- - Get current git branch
3551
- - Count git commits
3552
- - List modified files
3553
- - Check active Beads task
3580
+ - **IMPORTANT - Git State Scope:**
3581
+ * First check if .git exists in CURRENT directory (process.cwd())
3582
+ * ONLY capture git state if .git exists in current directory
3583
+ * DO NOT search parent directories for git repo
3584
+ * If no .git in current directory, skip git state capture
3585
+ - If .git exists in current directory:
3586
+ * Get current git branch
3587
+ * Count git commits
3588
+ * List modified files
3589
+ - Check active Beads task (from .beads directory if exists)
3554
3590
 
3555
3591
  3. **Add Update:**
3556
3592
  - Add timestamped update entry
3557
3593
  - Include your notes (or auto-generate)
3558
- - Include git state
3594
+ - Include git state ONLY if .git exists in current directory
3559
3595
  - Include Beads task if active
3560
3596
 
3561
3597
  4. **Save Session:**
@@ -3565,27 +3601,25 @@ Progress notes: $ARGUMENTS
3565
3601
  ## What Gets Captured
3566
3602
  - Timestamp of update
3567
3603
  - Your progress notes
3568
- - Current git branch
3569
- - Number of commits
3570
- - List of modified files
3604
+ - Git state (branch, commits, files) - ONLY if .git exists in current directory
3571
3605
  - Active Beads task (if any)
3572
3606
 
3573
3607
  ## Examples
3574
3608
 
3575
3609
  Auto-update (no notes):
3576
3610
  \`\`\`
3577
- /session:update
3611
+ /session-update
3578
3612
  \`\`\`
3579
3613
  *Auto-generates summary of recent work*
3580
3614
 
3581
3615
  With specific notes:
3582
3616
  \`\`\`
3583
- /session:update Fixed Next.js params issue
3617
+ /session-update Fixed Next.js params issue
3584
3618
  \`\`\`
3585
3619
 
3586
3620
  With detailed notes:
3587
3621
  \`\`\`
3588
- /session:update "Implemented OAuth flow with Google provider. Added callback handler and token validation."
3622
+ /session-update "Implemented OAuth flow with Google provider. Added callback handler and token validation."
3589
3623
  \`\`\`
3590
3624
 
3591
3625
  ## Notes
@@ -3595,11 +3629,11 @@ With detailed notes:
3595
3629
  - Beads task automatically linked`
3596
3630
  },
3597
3631
  {
3598
- name: "session:end",
3632
+ name: "session-end",
3599
3633
  description: "End current session with summary",
3600
3634
  category: "session",
3601
- usage: "/session:end",
3602
- examples: ["/session:end"],
3635
+ usage: "/session-end",
3636
+ examples: ["/session-end"],
3603
3637
  content: `End the current session and generate a comprehensive summary.
3604
3638
 
3605
3639
  ## Workflow
@@ -3629,7 +3663,10 @@ With detailed notes:
3629
3663
  - Mark session as ended
3630
3664
  - Set end time
3631
3665
  - Save session file
3632
- - Clear .current-session tracker
3666
+ - Determine session tracker file:
3667
+ * Try 'tty' command to get terminal identifier
3668
+ * If 'tty' works, clear .aikit/sessions/.current-<sanitized_tty>-session
3669
+ * If 'tty' fails, get parent PID and clear .aikit/sessions/.current-ppid-<PPID>-session
3633
3670
 
3634
3671
  ## Summary Includes
3635
3672
 
@@ -3684,17 +3721,20 @@ Lessons:
3684
3721
  - Can start new session after ending`
3685
3722
  },
3686
3723
  {
3687
- name: "session:current",
3724
+ name: "session-current",
3688
3725
  description: "Show current active session",
3689
3726
  category: "session",
3690
- usage: "/session:current",
3691
- examples: ["/session:current"],
3727
+ usage: "/session-current",
3728
+ examples: ["/session-current"],
3692
3729
  content: `Display information about the current active session.
3693
3730
 
3694
3731
  ## Workflow
3695
3732
 
3696
3733
  1. **Check Active Session:**
3697
- - Read .current-session file
3734
+ - Determine session tracker file:
3735
+ * Try 'tty' command to get terminal identifier
3736
+ * If 'tty' works, read .aikit/sessions/.current-<sanitized_tty>-session
3737
+ * If 'tty' fails, get parent PID and read .aikit/sessions/.current-ppid-<PPID>-session
3698
3738
  - Load session data
3699
3739
 
3700
3740
  2. **Display Session Info:**
@@ -3734,8 +3774,8 @@ Beads Task:
3734
3774
  - bead-001 (in-progress)
3735
3775
 
3736
3776
  Commands:
3737
- /session:update [notes] - Add progress
3738
- /session:end - Close session
3777
+ /session-update [notes] - Add progress
3778
+ /session-end - Close session
3739
3779
  \`\`\`
3740
3780
 
3741
3781
  ## Notes
@@ -3744,18 +3784,18 @@ Commands:
3744
3784
  - Displays recent progress`
3745
3785
  },
3746
3786
  {
3747
- name: "session:list",
3787
+ name: "session-list",
3748
3788
  description: "List all sessions",
3749
3789
  category: "session",
3750
- usage: "/session:list",
3751
- examples: ["/session:list"],
3790
+ usage: "/session-list",
3791
+ examples: ["/session-list"],
3752
3792
  content: `List all development sessions with summaries.
3753
3793
 
3754
3794
  ## Workflow
3755
3795
 
3756
3796
  1. **Scan Sessions Directory:**
3757
3797
  - Find all .md files in .aikit/sessions/
3758
- - Exclude .current-session
3798
+ - Exclude all .current-*-session files (terminal trackers)
3759
3799
 
3760
3800
  2. **Sort by Date:**
3761
3801
  - Newest sessions first
@@ -3798,16 +3838,16 @@ Total: 3 sessions
3798
3838
  - Shows both active and ended sessions
3799
3839
  - Most recent sessions first
3800
3840
  - Active session highlighted
3801
- - Use /session:show <id> for details`
3841
+ - Use /session-show <id> for details`
3802
3842
  },
3803
3843
  {
3804
- name: "session:show",
3844
+ name: "session-show",
3805
3845
  description: "Show details of a specific session",
3806
3846
  category: "session",
3807
- usage: "/session:show <session-id>",
3847
+ usage: "/session-show <session-id>",
3808
3848
  examples: [
3809
- "/session:show 2025-01-02-1430",
3810
- "/session:show 2025-01-02-1430-auth-refactor"
3849
+ "/session-show 2025-01-02-1430",
3850
+ "/session-show 2025-01-02-1430-auth-refactor"
3811
3851
  ],
3812
3852
  content: `Display full details of a specific session.
3813
3853
 
@@ -3878,14 +3918,14 @@ Successfully refactored authentication system...
3878
3918
  - Full session details displayed`
3879
3919
  },
3880
3920
  {
3881
- name: "session:search",
3921
+ name: "session-search",
3882
3922
  description: "Search sessions by keyword",
3883
3923
  category: "session",
3884
- usage: "/session:search <query>",
3924
+ usage: "/session-search <query>",
3885
3925
  examples: [
3886
- "/session:search oauth",
3887
- '/session:search "jwt"',
3888
- "/session:search authentication"
3926
+ "/session-search oauth",
3927
+ '/session-search "jwt"',
3928
+ "/session-search authentication"
3889
3929
  ],
3890
3930
  content: `Search for sessions matching a keyword.
3891
3931
 
@@ -3906,7 +3946,7 @@ Search query: $ARGUMENTS
3906
3946
 
3907
3947
  3. **Show Actions:**
3908
3948
  - List matching sessions
3909
- - Suggest /session:show for details
3949
+ - Suggest /session-show for details
3910
3950
 
3911
3951
  ## Example Output
3912
3952
  \`\`\`
@@ -3936,14 +3976,14 @@ Total: 2 matching sessions
3936
3976
  - Use partial IDs too`
3937
3977
  },
3938
3978
  {
3939
- name: "session:resume",
3979
+ name: "session-resume",
3940
3980
  description: "Resume a past session (load context)",
3941
3981
  category: "session",
3942
- usage: "/session:resume <session-id>",
3982
+ usage: "/session-resume <session-id>",
3943
3983
  examples: [
3944
- "/session:resume latest",
3945
- "/session:resume 2025-01-02-1430",
3946
- "/session:resume 2025-01-02-1430-auth-refactor"
3984
+ "/session-resume latest",
3985
+ "/session-resume 2025-01-02-1430",
3986
+ "/session-resume 2025-01-02-1430-auth-refactor"
3947
3987
  ],
3948
3988
  content: `Load context from a past session to resume work.
3949
3989
 
@@ -6163,6 +6203,282 @@ List approved dependencies here.
6163
6203
  }
6164
6204
  };
6165
6205
 
6206
+ // src/core/update-manager.ts
6207
+ init_esm_shims();
6208
+ init_version();
6209
+ import chalk2 from "chalk";
6210
+
6211
+ // src/utils/npm-client.ts
6212
+ init_esm_shims();
6213
+ import https from "https";
6214
+ async function getLatestVersion(packageName) {
6215
+ return new Promise((resolve) => {
6216
+ const url = `https://registry.npmjs.org/${packageName}`;
6217
+ https.get(url, (res) => {
6218
+ let data = "";
6219
+ res.on("data", (chunk) => {
6220
+ data += chunk;
6221
+ });
6222
+ res.on("end", () => {
6223
+ try {
6224
+ if (res.statusCode === 200) {
6225
+ const packageData = JSON.parse(data);
6226
+ const latestVersion = packageData["dist-tags"]?.latest;
6227
+ resolve(latestVersion || null);
6228
+ } else {
6229
+ resolve(null);
6230
+ }
6231
+ } catch {
6232
+ resolve(null);
6233
+ }
6234
+ });
6235
+ }).on("error", () => {
6236
+ resolve(null);
6237
+ }).setTimeout(5e3, () => {
6238
+ resolve(null);
6239
+ });
6240
+ });
6241
+ }
6242
+
6243
+ // src/utils/update-cache.ts
6244
+ init_esm_shims();
6245
+ init_paths();
6246
+ import { readFile as readFile8, writeFile as writeFile9, mkdir as mkdir8 } from "fs/promises";
6247
+ import { existsSync as existsSync5 } from "fs";
6248
+ import { join as join13 } from "path";
6249
+ var CACHE_FILE = ".update-cache.json";
6250
+ var DEFAULT_CACHE = {
6251
+ lastCheckTime: 0,
6252
+ lastCheckedVersion: "0.0.0",
6253
+ errorCount: 0
6254
+ };
6255
+ function getCachePath() {
6256
+ const configDir = paths.globalConfig();
6257
+ return join13(configDir, CACHE_FILE);
6258
+ }
6259
+ async function readCache() {
6260
+ try {
6261
+ const cachePath = getCachePath();
6262
+ if (!existsSync5(cachePath)) {
6263
+ return DEFAULT_CACHE;
6264
+ }
6265
+ const content = await readFile8(cachePath, "utf-8");
6266
+ const data = JSON.parse(content);
6267
+ return { ...DEFAULT_CACHE, ...data };
6268
+ } catch {
6269
+ return DEFAULT_CACHE;
6270
+ }
6271
+ }
6272
+ async function writeCache(data) {
6273
+ try {
6274
+ const cachePath = getCachePath();
6275
+ const configDir = paths.globalConfig();
6276
+ if (!existsSync5(configDir)) {
6277
+ await mkdir8(configDir, { recursive: true });
6278
+ }
6279
+ await writeFile9(cachePath, JSON.stringify(data, null, 2), "utf-8");
6280
+ } catch {
6281
+ }
6282
+ }
6283
+ async function setLastCheckTime(timestamp) {
6284
+ const cache = await readCache();
6285
+ cache.lastCheckTime = timestamp;
6286
+ await writeCache(cache);
6287
+ }
6288
+ async function setLastCheckedVersion(version) {
6289
+ const cache = await readCache();
6290
+ cache.lastCheckedVersion = version;
6291
+ await writeCache(cache);
6292
+ }
6293
+ async function setCompletedUpdate(version) {
6294
+ const cache = await readCache();
6295
+ cache.completedUpdate = version;
6296
+ cache.completedUpdateTime = Date.now();
6297
+ cache.errorCount = 0;
6298
+ cache.lastError = void 0;
6299
+ await writeCache(cache);
6300
+ }
6301
+ async function clearCompletedUpdate() {
6302
+ const cache = await readCache();
6303
+ cache.completedUpdate = void 0;
6304
+ cache.completedUpdateTime = void 0;
6305
+ await writeCache(cache);
6306
+ }
6307
+ async function incrementError(error) {
6308
+ const cache = await readCache();
6309
+ cache.errorCount += 1;
6310
+ cache.lastError = error;
6311
+ await writeCache(cache);
6312
+ }
6313
+
6314
+ // src/core/background-updater.ts
6315
+ init_esm_shims();
6316
+ init_paths();
6317
+ import { spawn } from "child_process";
6318
+ import { writeFile as writeFile10, mkdir as mkdir9 } from "fs/promises";
6319
+ import { join as join14 } from "path";
6320
+ async function spawnUpdateProcess(targetVersion) {
6321
+ try {
6322
+ const configDir = paths.globalConfig();
6323
+ const logsDir = join14(configDir, "logs");
6324
+ await mkdir9(logsDir, { recursive: true });
6325
+ const scriptContent = generateUpdateScript(targetVersion, logsDir);
6326
+ const scriptPath = join14(configDir, "update-script.js");
6327
+ await writeFile10(scriptPath, scriptContent, "utf-8");
6328
+ const child = spawn(process.execPath, [scriptPath], {
6329
+ detached: true,
6330
+ stdio: "ignore",
6331
+ windowsHide: true
6332
+ });
6333
+ child.unref();
6334
+ return true;
6335
+ } catch {
6336
+ return false;
6337
+ }
6338
+ }
6339
+ function generateUpdateScript(targetVersion, logsDir) {
6340
+ return `
6341
+ // AIKit Auto-Update Script
6342
+ // Generated automatically - DO NOT EDIT
6343
+
6344
+ const { spawn } = require('child_process');
6345
+ const { writeFile, appendFile } = require('fs').promises;
6346
+ const { join } = require('path');
6347
+
6348
+ const configDir = '${paths.globalConfig().replace(/\\/g, "\\\\")}';
6349
+ const logsDir = '${logsDir.replace(/\\/g, "\\\\")}';
6350
+ const cachePath = join(configDir, '.update-cache.json');
6351
+ const errorLogPath = join(logsDir, 'update-error.log');
6352
+ const targetVersion = '${targetVersion}';
6353
+
6354
+ async function logError(message) {
6355
+ const timestamp = new Date().toISOString();
6356
+ await appendFile(errorLogPath, \`[\${timestamp}] \${message}\\n\`);
6357
+ }
6358
+
6359
+ async function updateCache(version, error) {
6360
+ try {
6361
+ const fs = require('fs');
6362
+ let cache = { lastCheckTime: 0, lastCheckedVersion: '0.0.0', errorCount: 0 };
6363
+
6364
+ try {
6365
+ cache = JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
6366
+ } catch {}
6367
+
6368
+ if (error) {
6369
+ cache.errorCount = (cache.errorCount || 0) + 1;
6370
+ cache.lastError = error;
6371
+ } else {
6372
+ cache.completedUpdate = version;
6373
+ cache.completedUpdateTime = Date.now();
6374
+ cache.errorCount = 0;
6375
+ cache.lastError = undefined;
6376
+ }
6377
+
6378
+ await writeFile(cachePath, JSON.stringify(cache, null, 2));
6379
+ } catch {}
6380
+ }
6381
+
6382
+ async function runUpdate() {
6383
+ return new Promise((resolve) => {
6384
+ const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
6385
+ const child = spawn(npmCmd, ['install', '-g', '@tdsoft-tech/aikit@latest'], {
6386
+ stdio: 'pipe',
6387
+ });
6388
+
6389
+ let output = '';
6390
+ let errorOutput = '';
6391
+
6392
+ child.stdout.on('data', (data) => {
6393
+ output += data.toString();
6394
+ });
6395
+
6396
+ child.stderr.on('data', (data) => {
6397
+ errorOutput += data.toString();
6398
+ });
6399
+
6400
+ child.on('close', async (code) => {
6401
+ if (code === 0) {
6402
+ await updateCache(targetVersion, null);
6403
+ resolve(true);
6404
+ } else {
6405
+ const errorMsg = errorOutput || 'npm install failed';
6406
+ await logError(\`Update failed (code \${code}): \${errorMsg}\`);
6407
+ await updateCache(targetVersion, errorMsg);
6408
+ resolve(false);
6409
+ }
6410
+ });
6411
+
6412
+ child.on('error', async (err) => {
6413
+ await logError(\`Update error: \${err.message}\`);
6414
+ await updateCache(targetVersion, err.message);
6415
+ resolve(false);
6416
+ });
6417
+ });
6418
+ }
6419
+
6420
+ // Run update and exit
6421
+ runUpdate().then(() => process.exit(0));
6422
+ `;
6423
+ }
6424
+
6425
+ // src/core/update-manager.ts
6426
+ var CHECK_INTERVAL = 24 * 60 * 60 * 1e3;
6427
+ var PACKAGE_NAME = "@tdsoft-tech/aikit";
6428
+ async function shouldCheckForUpdates() {
6429
+ const cache = await readCache();
6430
+ const now = Date.now();
6431
+ return now - cache.lastCheckTime > CHECK_INTERVAL;
6432
+ }
6433
+ async function displayNotification() {
6434
+ const cache = await readCache();
6435
+ if (cache.completedUpdate) {
6436
+ const currentVersion = getVersion();
6437
+ if (isGreaterThan(cache.completedUpdate, currentVersion)) {
6438
+ console.log(chalk2.cyan.bold("\n\u2728 AIKit has been updated!\n"));
6439
+ console.log(chalk2.gray(` Version: ${currentVersion} \u2192 ${cache.completedUpdate}`));
6440
+ console.log(chalk2.gray(` Updated: Just now
6441
+ `));
6442
+ console.log(chalk2.gray("Run 'aikit --version' to verify.\n"));
6443
+ await clearCompletedUpdate();
6444
+ }
6445
+ }
6446
+ if (cache.errorCount >= 3 && cache.lastError) {
6447
+ console.log(chalk2.yellow.bold("\n\u26A0\uFE0F AIKit update failed\n"));
6448
+ console.log(chalk2.gray(` Last error: ${cache.lastError}`));
6449
+ console.log(chalk2.gray(" Check logs: ~/.config/aikit/logs/update-error.log\n"));
6450
+ }
6451
+ }
6452
+ async function performBackgroundUpdate(latestVersion) {
6453
+ const success = await spawnUpdateProcess(latestVersion);
6454
+ if (!success) {
6455
+ await incrementError("Failed to spawn update process");
6456
+ } else {
6457
+ await setCompletedUpdate(latestVersion);
6458
+ }
6459
+ }
6460
+ async function checkForUpdates() {
6461
+ try {
6462
+ await displayNotification();
6463
+ if (!await shouldCheckForUpdates()) {
6464
+ return;
6465
+ }
6466
+ const currentVersion = getVersion();
6467
+ const latestVersion = await getLatestVersion(PACKAGE_NAME);
6468
+ await setLastCheckTime(Date.now());
6469
+ await setLastCheckedVersion(currentVersion);
6470
+ if (!latestVersion || !isGreaterThan(latestVersion, currentVersion)) {
6471
+ return;
6472
+ }
6473
+ await performBackgroundUpdate(latestVersion);
6474
+ } catch {
6475
+ }
6476
+ }
6477
+ async function checkForUpdatesAsync() {
6478
+ checkForUpdates().catch(() => {
6479
+ });
6480
+ }
6481
+
6166
6482
  // src/index.ts
6167
6483
  init_logger();
6168
6484
  init_paths();
@@ -6178,6 +6494,7 @@ export {
6178
6494
  SkillEngine,
6179
6495
  ToolRegistry,
6180
6496
  getVersion as VERSION,
6497
+ checkForUpdatesAsync,
6181
6498
  defineTool,
6182
6499
  loadConfig,
6183
6500
  logger,