@hasna/prompts 0.2.2 → 0.3.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAMrC,wBAAgB,SAAS,IAAI,MAAM,CAsBlC;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAmBtC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAGD,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAqID,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0B5E;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAM5C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC3E"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAMrC,wBAAgB,SAAS,IAAI,MAAM,CAsBlC;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAmBtC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAGD,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAyJD,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0B5E;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAM5C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC3E"}
@@ -1,11 +1,22 @@
1
- import type { Prompt, CreatePromptInput, UpdatePromptInput, ListPromptsFilter } from "../types/index.js";
1
+ import type { Prompt, SlimPrompt, SaveResult, CreatePromptInput, UpdatePromptInput, ListPromptsFilter } from "../types/index.js";
2
+ export declare function promptToSaveResult(prompt: Prompt, created: boolean, duplicate_warning?: string | null): SaveResult;
2
3
  export declare function createPrompt(input: CreatePromptInput): Prompt;
3
4
  export declare function getPrompt(idOrSlug: string): Prompt | null;
4
5
  export declare function requirePrompt(idOrSlug: string): Prompt;
5
6
  export declare function listPrompts(filter?: ListPromptsFilter): Prompt[];
7
+ /** Slim version of listPrompts — no body, no full variables. Default for MCP listing. */
8
+ export declare function listPromptsSlim(filter?: ListPromptsFilter): SlimPrompt[];
6
9
  export declare function updatePrompt(idOrSlug: string, input: UpdatePromptInput): Prompt;
7
10
  export declare function deletePrompt(idOrSlug: string): void;
8
11
  export declare function usePrompt(idOrSlug: string): Prompt;
12
+ export declare function getTrending(days?: number, limit?: number): Array<{
13
+ id: string;
14
+ slug: string;
15
+ title: string;
16
+ uses: number;
17
+ }>;
18
+ export declare function setExpiry(idOrSlug: string, expiresAt: string | null): Prompt;
19
+ export declare function setNextPrompt(idOrSlug: string, nextSlug: string | null): Prompt;
9
20
  export declare function pinPrompt(idOrSlug: string, pinned: boolean): Prompt;
10
21
  export declare function upsertPrompt(input: CreatePromptInput, force?: boolean): {
11
22
  prompt: Prompt;
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/db/prompts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,MAAM,EACN,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EAGlB,MAAM,mBAAmB,CAAA;AA2B1B,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA0C7D;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,WAAW,CAAC,MAAM,GAAE,iBAAsB,GAAG,MAAM,EAAE,CA4CpE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA8C/E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAKnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,UAAQ,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,CA6BtI;AAED,wBAAgB,cAAc;;;;;YAOJ,MAAM;cAAQ,MAAM;cAAQ,MAAM;eAAS,MAAM;mBAAa,MAAM;;;YAGpE,MAAM;cAAQ,MAAM;cAAQ,MAAM;eAAS,MAAM;sBAAgB,MAAM;;;oBAG/D,MAAM;eAAS,MAAM;;;gBAGzB,MAAM;eAAS,MAAM;;EAGlD"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/db/prompts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EAGlB,MAAM,mBAAmB,CAAA;AA2B1B,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,CAWlH;AA2BD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA0C7D;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,WAAW,CAAC,MAAM,GAAE,iBAAsB,GAAG,MAAM,EAAE,CA4CpE;AAED,yFAAyF;AACzF,wBAAgB,eAAe,CAAC,MAAM,GAAE,iBAAsB,GAAG,UAAU,EAAE,CA+B5E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAiD/E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CASlD;AAED,wBAAgB,WAAW,CAAC,IAAI,SAAI,EAAE,KAAK,SAAK,GAAG,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAYlH;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAK5E;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAK/E;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAKnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,UAAQ,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,CA6BtI;AAED,wBAAgB,cAAc;;;;;YAOJ,MAAM;cAAQ,MAAM;cAAQ,MAAM;eAAS,MAAM;mBAAa,MAAM;;;YAGpE,MAAM;cAAQ,MAAM;cAAQ,MAAM;eAAS,MAAM;sBAAgB,MAAM;;;oBAG/D,MAAM;eAAS,MAAM;;;gBAGzB,MAAM;eAAS,MAAM;;EAGlD"}
package/dist/index.d.ts CHANGED
@@ -1,16 +1,16 @@
1
- export { createPrompt, getPrompt, requirePrompt, listPrompts, updatePrompt, deletePrompt, usePrompt, upsertPrompt, getPromptStats, pinPrompt } from "./db/prompts.js";
1
+ export { createPrompt, getPrompt, listPromptsSlim, promptToSaveResult, requirePrompt, listPrompts, updatePrompt, deletePrompt, usePrompt, upsertPrompt, getPromptStats, pinPrompt, setNextPrompt } from "./db/prompts.js";
2
2
  export { listVersions, getVersion, restoreVersion } from "./db/versions.js";
3
3
  export { listCollections, getCollection, ensureCollection, movePrompt } from "./db/collections.js";
4
4
  export { registerAgent, listAgents } from "./db/agents.js";
5
5
  export { getDatabase, getDbPath } from "./db/database.js";
6
6
  export { createProject, getProject, listProjects, deleteProject } from "./db/projects.js";
7
- export { searchPrompts, findSimilar } from "./lib/search.js";
7
+ export { searchPrompts, searchPromptsSlim, findSimilar } from "./lib/search.js";
8
8
  export { extractVariables, extractVariableInfo, renderTemplate, validateVars } from "./lib/template.js";
9
9
  export type { VariableInfo } from "./lib/template.js";
10
10
  export { importFromJson, exportToJson } from "./lib/importer.js";
11
11
  export { findDuplicates } from "./lib/duplicates.js";
12
12
  export type { DuplicateMatch } from "./lib/duplicates.js";
13
13
  export { generateSlug, uniqueSlug, generatePromptId } from "./lib/ids.js";
14
- export type { Prompt, PromptVersion, Collection, Agent, Project, TemplateVariable, PromptSource, CreatePromptInput, UpdatePromptInput, ListPromptsFilter, SearchResult, RenderResult, PromptStats, } from "./types/index.js";
14
+ export type { Prompt, SlimPrompt, SaveResult, SlimSearchResult, PromptVersion, Collection, Agent, Project, TemplateVariable, PromptSource, CreatePromptInput, UpdatePromptInput, ListPromptsFilter, SearchResult, RenderResult, PromptStats, } from "./types/index.js";
15
15
  export { PromptNotFoundError, VersionConflictError, DuplicateSlugError, TemplateRenderError, ProjectNotFoundError, } from "./types/index.js";
16
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACrK,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAClG,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGzF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG5D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACvG,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGzE,YAAY,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,KAAK,EACL,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACzN,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAClG,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGzF,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG/E,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACvG,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGzE,YAAY,EACV,MAAM,EACN,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,KAAK,EACL,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,kBAAkB,CAAA"}
package/dist/index.js CHANGED
@@ -128,6 +128,26 @@ function runMigrations(db) {
128
128
  CREATE INDEX IF NOT EXISTS idx_prompts_project_id ON prompts(project_id);
129
129
  `
130
130
  },
131
+ {
132
+ name: "005_chaining",
133
+ sql: `ALTER TABLE prompts ADD COLUMN next_prompt TEXT;`
134
+ },
135
+ {
136
+ name: "006_expiry",
137
+ sql: `ALTER TABLE prompts ADD COLUMN expires_at TEXT;`
138
+ },
139
+ {
140
+ name: "007_usage_log",
141
+ sql: `
142
+ CREATE TABLE IF NOT EXISTS usage_log (
143
+ id TEXT PRIMARY KEY,
144
+ prompt_id TEXT NOT NULL REFERENCES prompts(id) ON DELETE CASCADE,
145
+ used_at TEXT NOT NULL DEFAULT (datetime('now'))
146
+ );
147
+ CREATE INDEX IF NOT EXISTS idx_usage_log_prompt_id ON usage_log(prompt_id);
148
+ CREATE INDEX IF NOT EXISTS idx_usage_log_used_at ON usage_log(used_at);
149
+ `
150
+ },
131
151
  {
132
152
  name: "002_fts5",
133
153
  sql: `
@@ -419,6 +439,40 @@ class ProjectNotFoundError extends Error {
419
439
  }
420
440
 
421
441
  // src/db/prompts.ts
442
+ function rowToSlimPrompt(row) {
443
+ const variables = JSON.parse(row["variables"] || "[]");
444
+ return {
445
+ id: row["id"],
446
+ slug: row["slug"],
447
+ title: row["title"],
448
+ description: row["description"] ?? null,
449
+ collection: row["collection"],
450
+ tags: JSON.parse(row["tags"] || "[]"),
451
+ variable_names: variables.map((v) => v.name),
452
+ is_template: Boolean(row["is_template"]),
453
+ source: row["source"],
454
+ pinned: Boolean(row["pinned"]),
455
+ next_prompt: row["next_prompt"] ?? null,
456
+ expires_at: row["expires_at"] ?? null,
457
+ project_id: row["project_id"] ?? null,
458
+ use_count: row["use_count"],
459
+ last_used_at: row["last_used_at"] ?? null,
460
+ created_at: row["created_at"],
461
+ updated_at: row["updated_at"]
462
+ };
463
+ }
464
+ function promptToSaveResult(prompt, created, duplicate_warning) {
465
+ return {
466
+ id: prompt.id,
467
+ slug: prompt.slug,
468
+ title: prompt.title,
469
+ collection: prompt.collection,
470
+ is_template: prompt.is_template,
471
+ variable_names: prompt.variables.map((v) => v.name),
472
+ created,
473
+ duplicate_warning: duplicate_warning ?? null
474
+ };
475
+ }
422
476
  function rowToPrompt(row) {
423
477
  return {
424
478
  id: row["id"],
@@ -431,6 +485,8 @@ function rowToPrompt(row) {
431
485
  tags: JSON.parse(row["tags"] || "[]"),
432
486
  variables: JSON.parse(row["variables"] || "[]"),
433
487
  pinned: Boolean(row["pinned"]),
488
+ next_prompt: row["next_prompt"] ?? null,
489
+ expires_at: row["expires_at"] ?? null,
434
490
  project_id: row["project_id"] ?? null,
435
491
  is_template: Boolean(row["is_template"]),
436
492
  source: row["source"],
@@ -511,11 +567,45 @@ function listPrompts(filter = {}) {
511
567
  orderBy = `(CASE WHEN project_id = '${filter.project_id}' THEN 0 ELSE 1 END), pinned DESC, use_count DESC, updated_at DESC`;
512
568
  }
513
569
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
514
- const limit = filter.limit ?? 100;
570
+ const limit = filter.limit ?? 20;
515
571
  const offset = filter.offset ?? 0;
516
572
  const rows = db.query(`SELECT * FROM prompts ${where} ORDER BY ${orderBy} LIMIT ? OFFSET ?`).all(...params, limit, offset);
517
573
  return rows.map(rowToPrompt);
518
574
  }
575
+ function listPromptsSlim(filter = {}) {
576
+ const db = getDatabase();
577
+ const conditions = [];
578
+ const params = [];
579
+ if (filter.collection) {
580
+ conditions.push("collection = ?");
581
+ params.push(filter.collection);
582
+ }
583
+ if (filter.is_template !== undefined) {
584
+ conditions.push("is_template = ?");
585
+ params.push(filter.is_template ? 1 : 0);
586
+ }
587
+ if (filter.source) {
588
+ conditions.push("source = ?");
589
+ params.push(filter.source);
590
+ }
591
+ if (filter.tags && filter.tags.length > 0) {
592
+ const tagConds = filter.tags.map(() => "tags LIKE ?");
593
+ conditions.push(`(${tagConds.join(" OR ")})`);
594
+ for (const tag of filter.tags)
595
+ params.push(`%"${tag}"%`);
596
+ }
597
+ let orderBy = "pinned DESC, use_count DESC, updated_at DESC";
598
+ if (filter.project_id) {
599
+ conditions.push("(project_id = ? OR project_id IS NULL)");
600
+ params.push(filter.project_id);
601
+ orderBy = `(CASE WHEN project_id = '${filter.project_id}' THEN 0 ELSE 1 END), pinned DESC, use_count DESC, updated_at DESC`;
602
+ }
603
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
604
+ const limit = filter.limit ?? 20;
605
+ const offset = filter.offset ?? 0;
606
+ const rows = db.query(`SELECT id, slug, name, title, description, collection, tags, variables, is_template, source, pinned, next_prompt, expires_at, project_id, use_count, last_used_at, created_at, updated_at FROM prompts ${where} ORDER BY ${orderBy} LIMIT ? OFFSET ?`).all(...params, limit, offset);
607
+ return rows.map(rowToSlimPrompt);
608
+ }
519
609
  function updatePrompt(idOrSlug, input) {
520
610
  const db = getDatabase();
521
611
  const prompt = requirePrompt(idOrSlug);
@@ -529,6 +619,7 @@ function updatePrompt(idOrSlug, input) {
529
619
  description = COALESCE(?, description),
530
620
  collection = COALESCE(?, collection),
531
621
  tags = COALESCE(?, tags),
622
+ next_prompt = CASE WHEN ? IS NOT NULL THEN ? ELSE next_prompt END,
532
623
  variables = ?,
533
624
  is_template = ?,
534
625
  version = version + 1,
@@ -539,6 +630,8 @@ function updatePrompt(idOrSlug, input) {
539
630
  input.description ?? null,
540
631
  input.collection ?? null,
541
632
  input.tags ? JSON.stringify(input.tags) : null,
633
+ "next_prompt" in input ? input.next_prompt ?? "" : null,
634
+ "next_prompt" in input ? input.next_prompt ?? null : null,
542
635
  variables,
543
636
  is_template,
544
637
  prompt.id,
@@ -561,6 +654,13 @@ function usePrompt(idOrSlug) {
561
654
  const db = getDatabase();
562
655
  const prompt = requirePrompt(idOrSlug);
563
656
  db.run("UPDATE prompts SET use_count = use_count + 1, last_used_at = datetime('now') WHERE id = ?", [prompt.id]);
657
+ db.run("INSERT INTO usage_log (id, prompt_id) VALUES (?, ?)", [generateId("UL"), prompt.id]);
658
+ return requirePrompt(prompt.id);
659
+ }
660
+ function setNextPrompt(idOrSlug, nextSlug) {
661
+ const db = getDatabase();
662
+ const prompt = requirePrompt(idOrSlug);
663
+ db.run("UPDATE prompts SET next_prompt = ?, updated_at = datetime('now') WHERE id = ?", [nextSlug, prompt.id]);
564
664
  return requirePrompt(prompt.id);
565
665
  }
566
666
  function pinPrompt(idOrSlug, pinned) {
@@ -719,6 +819,22 @@ function deleteProject(idOrSlug) {
719
819
  db.run("DELETE FROM projects WHERE id = ?", [id]);
720
820
  }
721
821
  // src/lib/search.ts
822
+ function rowToSlimSearchResult(row, snippet) {
823
+ const variables = JSON.parse(row["variables"] || "[]");
824
+ return {
825
+ id: row["id"],
826
+ slug: row["slug"],
827
+ title: row["title"],
828
+ description: row["description"] ?? null,
829
+ collection: row["collection"],
830
+ tags: JSON.parse(row["tags"] || "[]"),
831
+ variable_names: variables.map((v) => v.name),
832
+ is_template: Boolean(row["is_template"]),
833
+ use_count: row["use_count"],
834
+ score: row["score"] ?? 1,
835
+ snippet
836
+ };
837
+ }
722
838
  function rowToSearchResult(row, snippet) {
723
839
  return {
724
840
  prompt: {
@@ -732,6 +848,8 @@ function rowToSearchResult(row, snippet) {
732
848
  tags: JSON.parse(row["tags"] || "[]"),
733
849
  variables: JSON.parse(row["variables"] || "[]"),
734
850
  pinned: Boolean(row["pinned"]),
851
+ next_prompt: row["next_prompt"] ?? null,
852
+ expires_at: row["expires_at"] ?? null,
735
853
  project_id: row["project_id"] ?? null,
736
854
  is_template: Boolean(row["is_template"]),
737
855
  source: row["source"],
@@ -799,9 +917,75 @@ function searchPrompts(query, filter = {}) {
799
917
  const rows = db.query(`SELECT *, 1 as score FROM prompts
800
918
  WHERE (name LIKE ? OR slug LIKE ? OR title LIKE ? OR body LIKE ? OR description LIKE ? OR tags LIKE ?)
801
919
  ORDER BY use_count DESC, updated_at DESC
802
- LIMIT ? OFFSET ?`).all(like, like, like, like, like, like, filter.limit ?? 50, filter.offset ?? 0);
920
+ LIMIT ? OFFSET ?`).all(like, like, like, like, like, like, filter.limit ?? 10, filter.offset ?? 0);
803
921
  return rows.map((r) => rowToSearchResult(r));
804
922
  }
923
+ function searchPromptsSlim(query, filter = {}) {
924
+ const db = getDatabase();
925
+ if (!query.trim()) {
926
+ return listPromptsSlim(filter).map((p) => ({
927
+ id: p.id,
928
+ slug: p.slug,
929
+ title: p.title,
930
+ description: p.description,
931
+ collection: p.collection,
932
+ tags: p.tags,
933
+ variable_names: p.variable_names,
934
+ is_template: p.is_template,
935
+ use_count: p.use_count,
936
+ score: 1
937
+ }));
938
+ }
939
+ if (hasFts(db)) {
940
+ const ftsQuery = escapeFtsQuery(query);
941
+ const conditions = [];
942
+ const params = [];
943
+ if (filter.collection) {
944
+ conditions.push("p.collection = ?");
945
+ params.push(filter.collection);
946
+ }
947
+ if (filter.is_template !== undefined) {
948
+ conditions.push("p.is_template = ?");
949
+ params.push(filter.is_template ? 1 : 0);
950
+ }
951
+ if (filter.source) {
952
+ conditions.push("p.source = ?");
953
+ params.push(filter.source);
954
+ }
955
+ if (filter.tags && filter.tags.length > 0) {
956
+ const tagConds = filter.tags.map(() => "p.tags LIKE ?");
957
+ conditions.push(`(${tagConds.join(" OR ")})`);
958
+ for (const tag of filter.tags)
959
+ params.push(`%"${tag}"%`);
960
+ }
961
+ if (filter.project_id) {
962
+ conditions.push("(p.project_id = ? OR p.project_id IS NULL)");
963
+ params.push(filter.project_id);
964
+ }
965
+ const where = conditions.length > 0 ? `AND ${conditions.join(" AND ")}` : "";
966
+ const limit = filter.limit ?? 10;
967
+ const offset = filter.offset ?? 0;
968
+ try {
969
+ const rows2 = db.query(`SELECT p.id, p.slug, p.name, p.title, p.description, p.collection, p.tags, p.variables,
970
+ p.is_template, p.use_count, bm25(prompts_fts) as score,
971
+ snippet(prompts_fts, 2, '[', ']', '...', 10) as snippet
972
+ FROM prompts p
973
+ INNER JOIN prompts_fts ON prompts_fts.rowid = p.rowid
974
+ WHERE prompts_fts MATCH ?
975
+ ${where}
976
+ ORDER BY bm25(prompts_fts)
977
+ LIMIT ? OFFSET ?`).all(ftsQuery, ...params, limit, offset);
978
+ return rows2.map((r) => rowToSlimSearchResult(r, r["snippet"]));
979
+ } catch {}
980
+ }
981
+ const like = `%${query}%`;
982
+ const rows = db.query(`SELECT id, slug, name, title, description, collection, tags, variables, is_template, use_count, 1 as score
983
+ FROM prompts
984
+ WHERE (name LIKE ? OR slug LIKE ? OR title LIKE ? OR body LIKE ? OR description LIKE ? OR tags LIKE ?)
985
+ ORDER BY use_count DESC, updated_at DESC
986
+ LIMIT ? OFFSET ?`).all(like, like, like, like, like, like, filter.limit ?? 10, filter.offset ?? 0);
987
+ return rows.map((r) => rowToSlimSearchResult(r));
988
+ }
805
989
  function findSimilar(promptId, limit = 5) {
806
990
  const db = getDatabase();
807
991
  const prompt = db.query("SELECT * FROM prompts WHERE id = ?").get(promptId);
@@ -860,14 +1044,18 @@ export {
860
1044
  upsertPrompt,
861
1045
  updatePrompt,
862
1046
  uniqueSlug,
1047
+ setNextPrompt,
1048
+ searchPromptsSlim,
863
1049
  searchPrompts,
864
1050
  restoreVersion,
865
1051
  requirePrompt,
866
1052
  renderTemplate,
867
1053
  registerAgent,
1054
+ promptToSaveResult,
868
1055
  pinPrompt,
869
1056
  movePrompt,
870
1057
  listVersions,
1058
+ listPromptsSlim,
871
1059
  listPrompts,
872
1060
  listProjects,
873
1061
  listCollections,
@@ -0,0 +1,16 @@
1
+ export interface AuditIssue {
2
+ type: "orphaned-project" | "empty-collection" | "missing-version-history" | "near-duplicate-slug" | "expired";
3
+ severity: "error" | "warn" | "info";
4
+ prompt_id?: string;
5
+ slug?: string;
6
+ message: string;
7
+ }
8
+ export interface AuditReport {
9
+ issues: AuditIssue[];
10
+ errors: number;
11
+ warnings: number;
12
+ info: number;
13
+ checked_at: string;
14
+ }
15
+ export declare function runAudit(): AuditReport;
16
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/lib/audit.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,GAAG,yBAAyB,GAAG,qBAAqB,GAAG,SAAS,CAAA;IAC7G,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,QAAQ,IAAI,WAAW,CAuFtC"}
@@ -0,0 +1,3 @@
1
+ export declare function generateZshCompletion(): string;
2
+ export declare function generateBashCompletion(): string;
3
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/lib/completion.ts"],"names":[],"mappings":"AAYA,wBAAgB,qBAAqB,IAAI,MAAM,CAkE9C;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAgD/C"}
@@ -0,0 +1,8 @@
1
+ export interface DiffLine {
2
+ type: "added" | "removed" | "unchanged";
3
+ content: string;
4
+ lineNum?: number;
5
+ }
6
+ export declare function diffTexts(a: string, b: string): DiffLine[];
7
+ export declare function formatDiff(lines: DiffLine[]): string;
8
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/lib/diff.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,CAAA;IACvC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAmC1D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAMpD"}
@@ -31,6 +31,14 @@ export declare function importFromMarkdown(files: Array<{
31
31
  filename: string;
32
32
  content: string;
33
33
  }>, changedBy?: string): ImportResult;
34
+ export interface SlashCommandScanResult {
35
+ scanned: Array<{
36
+ source: string;
37
+ file: string;
38
+ }>;
39
+ imported: ImportResult;
40
+ }
41
+ export declare function scanAndImportSlashCommands(rootDir: string, changedBy?: string): SlashCommandScanResult;
34
42
  export declare function importFromClaudeCommands(files: Array<{
35
43
  filename: string;
36
44
  content: string;
@@ -1 +1 @@
1
- {"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../../src/lib/importer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqB,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAElE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC/C;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,CA0BpF;AAED,wBAAgB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG;IACjD,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAGA;AAaD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED,wBAAgB,qBAAqB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAMvG;AAGD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CA8B1F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,CAKxH;AAKD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EACnD,SAAS,CAAC,EAAE,MAAM,GACjB,YAAY,CAad"}
1
+ {"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../../src/lib/importer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqB,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAElE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC/C;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,CA0BpF;AAED,wBAAgB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG;IACjD,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAGA;AAaD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED,wBAAgB,qBAAqB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAMvG;AAGD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CA8B1F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,CAKxH;AAGD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChD,QAAQ,EAAE,YAAY,CAAA;CACvB;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,sBAAsB,CAgDxB;AAKD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EACnD,SAAS,CAAC,EAAE,MAAM,GACjB,YAAY,CAad"}
@@ -1,4 +1,6 @@
1
- import type { SearchResult, ListPromptsFilter } from "../types/index.js";
1
+ import type { SlimSearchResult, SearchResult, ListPromptsFilter } from "../types/index.js";
2
2
  export declare function searchPrompts(query: string, filter?: Omit<ListPromptsFilter, "q">): SearchResult[];
3
+ /** Slim search — returns only metadata + snippet, no body. Default for MCP. */
4
+ export declare function searchPromptsSlim(query: string, filter?: Omit<ListPromptsFilter, "q">): SlimSearchResult[];
3
5
  export declare function findSimilar(promptId: string, limit?: number): SearchResult[];
4
6
  //# sourceMappingURL=search.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAwCxE,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAM,GACxC,YAAY,EAAE,CAwEhB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,YAAY,EAAE,CAmCvE"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AA4D1F,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAM,GACxC,YAAY,EAAE,CAwEhB;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAM,GACxC,gBAAgB,EAAE,CA2DpB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,YAAY,EAAE,CAmCvE"}