@skilltap/core 0.5.5 → 0.5.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilltap/core",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "description": "Core library for skilltap — agent skill management",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/install.ts CHANGED
@@ -63,8 +63,12 @@ export type InstallOptions = {
63
63
  ) => Promise<boolean>;
64
64
  /** Called after static scan finds warnings — "Run semantic scan?" prompt. */
65
65
  onOfferSemantic?: () => Promise<boolean>;
66
- /** Called with progress during semantic scan. */
67
- onSemanticProgress?: (completed: number, total: number) => void;
66
+ /** Called when static scan begins for a skill. */
67
+ onStaticScanStart?: (skillName: string) => void;
68
+ /** Called when semantic scan begins for a skill. */
69
+ onSemanticScanStart?: (skillName: string) => void;
70
+ /** Called after each chunk is evaluated during semantic scan. */
71
+ onSemanticProgress?: (completed: number, total: number, score: number, reason: string) => void;
68
72
  /** Called after all scans pass cleanly, before placement. Return false to cancel. */
69
73
  onConfirmInstall?: (skillNames: string[]) => Promise<boolean>;
70
74
  /** Called when a skill is already installed. Return "update" to update it instead, or "abort" to cancel. */
@@ -159,9 +163,11 @@ async function resolveTapName(
159
163
  async function runSecurityScan(
160
164
  selected: ScannedSkill[],
161
165
  onWarnings?: InstallOptions["onWarnings"],
166
+ onStaticScanStart?: InstallOptions["onStaticScanStart"],
162
167
  ): Promise<Result<StaticWarning[], ScanError | UserError>> {
163
168
  const allWarnings: StaticWarning[] = [];
164
169
  for (const skill of selected) {
170
+ onStaticScanStart?.(skill.name);
165
171
  const scanResult = await scanStatic(skill.path);
166
172
  if (!scanResult.ok) return scanResult;
167
173
  if (scanResult.value.length > 0) {
@@ -501,7 +507,7 @@ export async function installSkill(
501
507
 
502
508
  // 6.5. Security scan (unless skipped)
503
509
  if (!options.skipScan) {
504
- const scanResult = await runSecurityScan(selected, options.onWarnings);
510
+ const scanResult = await runSecurityScan(selected, options.onWarnings, options.onStaticScanStart);
505
511
  if (!scanResult.ok) return scanResult;
506
512
  allWarnings.push(...scanResult.value);
507
513
  }
@@ -515,6 +521,7 @@ export async function installSkill(
515
521
 
516
522
  if (shouldRunSemantic && !options.skipScan && options.agent) {
517
523
  for (const skill of selected) {
524
+ options.onSemanticScanStart?.(skill.name);
518
525
  const semResult = await scanSemantic(skill.path, options.agent, {
519
526
  threshold: options.threshold,
520
527
  onProgress: options.onSemanticProgress,
@@ -18,7 +18,8 @@ export type SemanticWarning = {
18
18
 
19
19
  export type SemanticScanOptions = {
20
20
  threshold?: number;
21
- onProgress?: (completed: number, total: number) => void;
21
+ onScanStart?: (total: number) => void;
22
+ onProgress?: (completed: number, total: number, score: number, reason: string) => void;
22
23
  };
23
24
 
24
25
  // ── Constants ──
@@ -141,6 +142,8 @@ export async function scanSemantic(
141
142
  const chunks = await chunkSkillDir(dir);
142
143
  if (chunks.length === 0) return ok([]);
143
144
 
145
+ opts?.onScanStart?.(chunks.length);
146
+
144
147
  const randomSuffix = randomBytes(4).toString("hex");
145
148
  const warnings: SemanticWarning[] = [];
146
149
 
@@ -175,10 +178,10 @@ export async function scanSemantic(
175
178
  const result = await adapter.invoke(prompt);
176
179
 
177
180
  completed++;
178
- opts?.onProgress?.(completed, chunks.length);
179
181
 
180
182
  if (result.ok) {
181
183
  const { score, reason } = result.value;
184
+ opts?.onProgress?.(completed, chunks.length, score, reason);
182
185
  if (score >= threshold) {
183
186
  warnings.push({
184
187
  file: chunk.file,
@@ -189,6 +192,9 @@ export async function scanSemantic(
189
192
  raw: truncateRaw(chunk.content),
190
193
  });
191
194
  }
195
+ } else {
196
+ // Invoke failed — advance progress with score 0
197
+ opts?.onProgress?.(completed, chunks.length, 0, "");
192
198
  }
193
199
  // If invoke fails, treat as score 0 — skip (fail open)
194
200
  },