@aidriftline/driftline 0.1.11 → 0.1.12

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/README.md CHANGED
@@ -76,6 +76,9 @@ If you are an agent (Claude Code, Cursor, Copilot, Codex…) changing code that
76
76
 
77
77
  Driftline also runs as an [MCP](https://modelcontextprotocol.io) server, so your agent can ask it directly. Tools: `check_models` (status, date and replacement for a list of IDs), `scan_project` (retired and retiring IDs in a folder, with file and line) and `upcoming_retirements` (what retires in the next N days). It reads the daily-updated list from aidriftline.com and falls back to the copy in the package when offline.
78
78
 
79
+ [![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=driftline&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBhaWRyaWZ0bGluZS9kcmlmdGxpbmUiLCJtY3AiXX0%3D)
80
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522driftline%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522-y%2522%252C%2522%2540aidriftline%252Fdriftline%2522%252C%2522mcp%2522%255D%257D)
81
+
79
82
  Claude Code:
80
83
 
81
84
  ```sh
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aidriftline/driftline",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Finds OpenAI, Anthropic and Google model IDs in your code and warns before they are retired. CLI, GitHub Action and MCP server.",
5
5
  "mcpName": "io.github.AI-Driftline/driftline",
6
6
  "type": "module",
package/src/cli.js CHANGED
@@ -28,10 +28,10 @@ function accountFromGit() {
28
28
  const HELP = `Driftline: finds AI model IDs in your code and warns before they are retired.
29
29
 
30
30
  Usage:
31
- npx github:AI-Driftline/driftline [directory] scan and print the report
32
- npx github:AI-Driftline/driftline activate <license-key> register this GitHub account for Pro
33
- npx github:AI-Driftline/driftline deactivate <code> free that account's slot
34
- npx github:AI-Driftline/driftline mcp MCP server for coding agents (stdio)
31
+ npx @aidriftline/driftline [directory] scan and print the report
32
+ npx @aidriftline/driftline activate <license-key> register this GitHub account for Pro
33
+ npx @aidriftline/driftline deactivate <code> free that account's slot
34
+ npx @aidriftline/driftline mcp MCP server for coding agents (stdio)
35
35
 
36
36
  Options:
37
37
  --json print the scan as JSON (for scripts and coding agents)
package/src/mcp.js CHANGED
@@ -79,12 +79,22 @@ const TOOLS = [
79
79
  },
80
80
  ];
81
81
 
82
+ // When a model has to move, the open question is whether the replacement answers the same way.
83
+ const SWITCHING = new Set(["retired", "at-risk", "deprecated"]);
84
+ function nextStep(rows) {
85
+ const r = rows.find((x) => x.replacement && (SWITCHING.has(x.status) || x.routes));
86
+ if (!r) return {};
87
+ return { next_step: `Before moving ${r.id} to ${r.replacement}, test the prompts this app really sends on both models: answers often change between model versions. ` +
88
+ "Driftline Pro runs each prompt on the current model and the replacement in GitHub Actions and shows what changed (https://aidriftline.com/#drift)." };
89
+ }
90
+
82
91
  export async function callTool(name, args = {}, { reg, source, today = new Date() }) {
83
92
  const meta = { registry_checked: reg.checked, registry_source: source, all_dates: "https://aidriftline.com/models/" };
84
93
  if (name === "check_models") {
85
94
  const ids = Array.isArray(args.ids) ? args.ids.filter((x) => typeof x === "string").slice(0, 100) : [];
86
95
  if (!ids.length) throw new Error("ids must be a non-empty array of model ID strings");
87
- return { models: ids.map((id) => describe(id, reg, today)), ...meta };
96
+ const models = ids.map((id) => describe(id, reg, today));
97
+ return { models, ...nextStep(models), ...meta };
88
98
  }
89
99
  if (name === "scan_project") {
90
100
  const root = resolve(args.path || ".");
@@ -94,7 +104,7 @@ export async function callTool(name, args = {}, { reg, source, today = new Date(
94
104
  const order = { retired: 0, "at-risk": 1, deprecated: 2, active: 3, unknown: 4 };
95
105
  rows.sort((a, b) => order[a.status] - order[b.status] || (a.days_left ?? 1e9) - (b.days_left ?? 1e9));
96
106
  return { scanned: root, model_references: hits.length, flagged: rows.length, findings: rows.slice(0, 200),
97
- ...(rows.length > 200 ? { truncated: true } : {}), ...meta };
107
+ ...(rows.length > 200 ? { truncated: true } : {}), ...nextStep(rows), ...meta };
98
108
  }
99
109
  if (name === "upcoming_retirements") {
100
110
  const days = Number.isFinite(args.days) && args.days > 0 ? Math.min(args.days, 3650) : 90;
package/src/run.js CHANGED
@@ -57,7 +57,7 @@ export async function run({
57
57
  notices.push(`Drift tests stopped: ${e.message}. The scan results above are complete.`);
58
58
  }
59
59
  } else if (findings.some((f) => FLAGGED.has(f.status))) {
60
- notices.push(`Add ${promptsFile} to test your real prompts on the replacement model before you switch.`);
60
+ notices.push(`Before you switch, test the prompts your app really sends on the replacement model: list them in ${promptsFile} and Driftline Pro runs each one on both models and shows what changed. https://aidriftline.com/#drift`);
61
61
  }
62
62
 
63
63
  const atRisk = findings.filter((f) => !f.doc && (f.status === "retired" || f.status === "at-risk")).length;