@orderful/droid 0.11.1 → 0.13.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/src/lib/config.ts CHANGED
@@ -2,11 +2,16 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2
2
  import { homedir } from 'os';
3
3
  import { join } from 'path';
4
4
  import YAML from 'yaml';
5
- import { Platform, BuiltInOutput, type DroidConfig, type LegacyDroidConfig, type SkillOverrides } from './types.js';
5
+ import { Platform, BuiltInOutput, type DroidConfig, type LegacyDroidConfig, type SkillOverrides, type AutoUpdateConfig } from './types.js';
6
6
 
7
7
  const CONFIG_DIR = join(homedir(), '.droid');
8
8
  const CONFIG_FILE = join(CONFIG_DIR, 'config.yaml');
9
9
 
10
+ const DEFAULT_AUTO_UPDATE: AutoUpdateConfig = {
11
+ app: false, // Opt-in: user must enable
12
+ tools: true, // Opt-out: enabled by default (tools only update when app updates)
13
+ };
14
+
10
15
  const DEFAULT_CONFIG: DroidConfig = {
11
16
  platform: Platform.ClaudeCode,
12
17
  user_mention: '@user',
@@ -194,3 +199,27 @@ export function saveSkillOverrides(skillName: string, overrides: SkillOverrides)
194
199
  const content = YAML.stringify(overrides, { indent: 2 });
195
200
  writeFileSync(overridesPath, content, 'utf-8');
196
201
  }
202
+
203
+ /**
204
+ * Get auto-update config with defaults applied
205
+ */
206
+ export function getAutoUpdateConfig(): AutoUpdateConfig {
207
+ const config = loadConfig();
208
+ return {
209
+ ...DEFAULT_AUTO_UPDATE,
210
+ ...config.auto_update,
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Update auto-update config
216
+ */
217
+ export function setAutoUpdateConfig(updates: Partial<AutoUpdateConfig>): void {
218
+ const config = loadConfig();
219
+ config.auto_update = {
220
+ ...DEFAULT_AUTO_UPDATE,
221
+ ...config.auto_update,
222
+ ...updates,
223
+ };
224
+ saveConfig(config);
225
+ }
package/src/lib/tools.ts CHANGED
@@ -4,6 +4,7 @@ import { fileURLToPath } from 'url';
4
4
  import YAML from 'yaml';
5
5
  import { loadConfig } from './config.js';
6
6
  import { type ToolManifest, type ToolIncludes, getPlatformTools } from './types.js';
7
+ import { compareSemver } from './version.js';
7
8
 
8
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
10
  const BUNDLED_TOOLS_DIR = join(__dirname, '../tools');
@@ -112,29 +113,67 @@ export function getInstalledToolVersion(toolName: string): string | null {
112
113
  return null;
113
114
  }
114
115
 
115
- /**
116
- * Check if a tool has an update available
117
- */
118
- export function getToolUpdateStatus(toolName: string): {
116
+ export interface ToolUpdateInfo {
117
+ name: string;
119
118
  hasUpdate: boolean;
120
119
  installedVersion: string | null;
121
120
  bundledVersion: string | null;
122
- } {
121
+ }
122
+
123
+ /**
124
+ * Check if a tool has an update available
125
+ */
126
+ export function getToolUpdateStatus(toolName: string): ToolUpdateInfo {
123
127
  const installedVersion = getInstalledToolVersion(toolName);
124
128
  const tool = getBundledTools().find(t => t.name === toolName);
125
129
  const bundledVersion = tool?.version || null;
126
130
 
127
131
  if (!installedVersion || !bundledVersion) {
128
132
  return {
133
+ name: toolName,
129
134
  hasUpdate: false,
130
135
  installedVersion,
131
136
  bundledVersion,
132
137
  };
133
138
  }
134
139
 
140
+ // Use semver comparison: bundled > installed means update available
141
+ const hasUpdate = compareSemver(bundledVersion, installedVersion) > 0;
142
+
135
143
  return {
136
- hasUpdate: bundledVersion !== installedVersion,
144
+ name: toolName,
145
+ hasUpdate,
137
146
  installedVersion,
138
147
  bundledVersion,
139
148
  };
140
149
  }
150
+
151
+ /**
152
+ * Get all installed tools that have updates available
153
+ */
154
+ export function getToolsWithUpdates(): ToolUpdateInfo[] {
155
+ const config = loadConfig();
156
+ const installedTools = getPlatformTools(config);
157
+ const bundledTools = getBundledTools();
158
+
159
+ const toolsWithUpdates: ToolUpdateInfo[] = [];
160
+
161
+ // Check each bundled tool to see if it's installed and has an update
162
+ for (const tool of bundledTools) {
163
+ // Find if any of the tool's required skills are installed
164
+ const requiredSkills = tool.includes.skills
165
+ .filter(s => s.required)
166
+ .map(s => s.name);
167
+
168
+ const isInstalled = requiredSkills.some(skillName => skillName in installedTools);
169
+
170
+ if (isInstalled) {
171
+ const updateStatus = getToolUpdateStatus(tool.name);
172
+ if (updateStatus.hasUpdate) {
173
+ toolsWithUpdates.push(updateStatus);
174
+ }
175
+ }
176
+ }
177
+
178
+ return toolsWithUpdates;
179
+ }
package/src/lib/types.ts CHANGED
@@ -42,12 +42,18 @@ export interface PlatformConfig {
42
42
  tools: Record<string, InstalledSkill>;
43
43
  }
44
44
 
45
+ export interface AutoUpdateConfig {
46
+ app: boolean; // Auto-update droid CLI (default: false)
47
+ tools: boolean; // Auto-update installed tools (default: true)
48
+ }
49
+
45
50
  export interface DroidConfig {
46
51
  platform: Platform;
47
52
  user_mention: string;
48
53
  output_preference: OutputPreference;
49
54
  git_username: string;
50
55
  platforms: Record<string, PlatformConfig>;
56
+ auto_update?: AutoUpdateConfig;
51
57
  }
52
58
 
53
59
  // Legacy config structure for migration
@@ -0,0 +1,18 @@
1
+ name: droid
2
+ description: "Core droid meta-skill for update awareness and discovery. Notifies about droid updates from within Claude Code."
3
+ version: 0.1.0
4
+ status: beta
5
+
6
+ # System tool - always stays current regardless of auto-update settings
7
+ system: true
8
+
9
+ includes:
10
+ skills:
11
+ - name: droid
12
+ required: true
13
+ commands: []
14
+ agents: []
15
+
16
+ dependencies: []
17
+
18
+ config_schema: {}
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: droid
3
+ description: "Core droid meta-skill for update awareness. Checks for droid updates and notifies users from within Claude Code."
4
+ globs:
5
+ - "**/*"
6
+ alwaysApply: false
7
+ ---
8
+
9
+ # Droid
10
+
11
+ Core meta-skill for droid update awareness.
12
+
13
+ ## Purpose
14
+
15
+ Notify users about droid CLI updates from within Claude Code. Users who don't run `droid` often may miss updates - this skill proactively nudges them.
16
+
17
+ ## Update Checking
18
+
19
+ ### When to Check
20
+
21
+ 1. **Proactively** - Check for **droid CLI updates** once near the start of each session. This is specifically about the `@orderful/droid` npm package, not general software updates.
22
+ 2. **On request** - When user explicitly asks about droid updates ("any droid updates?", "is droid up to date?", "check droid version")
23
+
24
+ ### How to Check
25
+
26
+ Run this command to get the latest published version:
27
+
28
+ ```bash
29
+ npm view @orderful/droid version 2>/dev/null
30
+ ```
31
+
32
+ Compare against the installed version. To find the installed version, check:
33
+
34
+ ```bash
35
+ cat ~/.droid/config.yaml | grep -A1 "droid:" | grep "version:" | awk '{print $2}'
36
+ ```
37
+
38
+ Or if droid skill isn't in config yet, check the npm global:
39
+
40
+ ```bash
41
+ npm list -g @orderful/droid --depth=0 2>/dev/null | grep @orderful/droid | awk -F@ '{print $NF}'
42
+ ```
43
+
44
+ ### Update Notification Format
45
+
46
+ When an update is available, output this notification:
47
+
48
+ ```
49
+ [● ●] "I suggest a new strategy: let the Wookiee update."
50
+
51
+ Droid v{latest} is available (you have v{current}).
52
+ Run `droid` to update, then restart Claude Code.
53
+ ```
54
+
55
+ Replace `{latest}` with the npm version and `{current}` with the installed version.
56
+
57
+ ### Session Tracking
58
+
59
+ **Important:** Only show the update notification ONCE per session. After showing it:
60
+ - Do not show it again in the same conversation
61
+ - Do not repeat it even if user continues chatting
62
+
63
+ If the user explicitly asks about updates again, you can confirm whether they're up to date.
64
+
65
+ ## Examples
66
+
67
+ ### Proactive Check (Session Start)
68
+
69
+ User: "Help me refactor this function"
70
+
71
+ *[Claude checks for droid updates as part of initial response]*
72
+
73
+ ```
74
+ [● ●] "I suggest a new strategy: let the Wookiee update."
75
+
76
+ Droid v0.12.0 is available (you have v0.11.0).
77
+ Run `droid` to update, then restart Claude Code.
78
+
79
+ ---
80
+
81
+ Now, let me help you refactor that function...
82
+ ```
83
+
84
+ ### User Request
85
+
86
+ User: "Is droid up to date?"
87
+
88
+ ```
89
+ Let me check...
90
+
91
+ [● ●] "I suggest a new strategy: let the Wookiee update."
92
+
93
+ Droid v0.12.0 is available (you have v0.11.0).
94
+ Run `droid` to update, then restart Claude Code.
95
+ ```
96
+
97
+ Or if already up to date:
98
+
99
+ ```
100
+ [● ●] Droid is up to date (v0.12.0).
101
+ ```
102
+
103
+ ### Already Notified This Session
104
+
105
+ User: "Any other updates?"
106
+
107
+ ```
108
+ I already mentioned the droid update earlier. You're on v0.11.0, latest is v0.12.0.
109
+ Run `droid` when you're ready to update.
110
+ ```
111
+
112
+ ## Behaviour Notes
113
+
114
+ - Keep the check quick (timeout after 3 seconds)
115
+ - If the npm check fails (network issues), silently skip - don't error
116
+ - The droid eyes `[● ●]` and Star Wars quote are intentional branding - always include them
117
+ - Be helpful but not annoying - one nudge per session is enough
@@ -0,0 +1,7 @@
1
+ name: droid
2
+ description: "Core droid meta-skill for update awareness. Checks for droid updates and notifies users from within Claude Code."
3
+ version: 0.1.0
4
+ status: beta
5
+ dependencies: []
6
+ provides_output: false
7
+ config_schema: {}