@aidriftline/driftline 0.1.10 → 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
@@ -21,10 +21,10 @@ It runs inside your own CI with your own API keys. There is no Driftline server:
21
21
  3. Activate your Pro key once per GitHub account or organization, from inside one of its repositories:
22
22
 
23
23
  ```sh
24
- npx github:AI-Driftline/driftline activate <your-license-key>
24
+ npx @aidriftline/driftline activate <your-license-key>
25
25
  ```
26
26
 
27
- It prints a license code. Save that code as the secret `DRIFTLINE_LICENSE_KEY`. A key works on up to 3 GitHub accounts or organizations; `npx github:AI-Driftline/driftline deactivate <code>` frees one.
27
+ It prints a license code. Save that code as the secret `DRIFTLINE_LICENSE_KEY`. A key works on up to 3 GitHub accounts or organizations; `npx @aidriftline/driftline deactivate <code>` frees one.
28
28
 
29
29
  ## Inputs
30
30
 
@@ -62,24 +62,27 @@ Text is compared with word and word-pair overlap. JSON is compared field by fiel
62
62
  No install, no key:
63
63
 
64
64
  ```sh
65
- npx github:AI-Driftline/driftline path/to/your/repo # report
66
- npx github:AI-Driftline/driftline path/to/your/repo --json # same, as JSON
65
+ npx @aidriftline/driftline path/to/your/repo # report
66
+ npx @aidriftline/driftline path/to/your/repo --json # same, as JSON
67
67
  ```
68
68
 
69
69
  Exit code 1 means a retired model is used in code.
70
70
 
71
71
  ## For AI coding agents
72
72
 
73
- If you are an agent (Claude Code, Cursor, Copilot, Codex…) changing code that calls OpenAI, Anthropic or Google: run `npx -y github:AI-Driftline/driftline . --json` before you pick or keep a model ID, and do not introduce an ID whose `status` is `retired` or `at-risk`. Without a shell, look the ID up in [`registry/models.json`](registry/models.json) or at `https://aidriftline.com/models/<model-id>/`. More, including a snippet for `AGENTS.md` / `CLAUDE.md`: [aidriftline.com/agents](https://aidriftline.com/agents/).
73
+ If you are an agent (Claude Code, Cursor, Copilot, Codex…) changing code that calls OpenAI, Anthropic or Google: run `npx -y @aidriftline/driftline . --json` before you pick or keep a model ID, and do not introduce an ID whose `status` is `retired` or `at-risk`. Without a shell, look the ID up in [`registry/models.json`](registry/models.json) or at `https://aidriftline.com/models/<model-id>/`. More, including a snippet for `AGENTS.md` / `CLAUDE.md`: [aidriftline.com/agents](https://aidriftline.com/agents/).
74
74
 
75
75
  ### MCP server
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
82
- claude mcp add driftline -- npx -y github:AI-Driftline/driftline mcp
85
+ claude mcp add driftline -- npx -y @aidriftline/driftline mcp
83
86
  ```
84
87
 
85
88
  Cursor, Windsurf, Claude Desktop and other clients (`mcp.json` / `claude_desktop_config.json`):
@@ -87,7 +90,7 @@ Cursor, Windsurf, Claude Desktop and other clients (`mcp.json` / `claude_desktop
87
90
  ```json
88
91
  {
89
92
  "mcpServers": {
90
- "driftline": { "command": "npx", "args": ["-y", "github:AI-Driftline/driftline", "mcp"] }
93
+ "driftline": { "command": "npx", "args": ["-y", "@aidriftline/driftline", "mcp"] }
91
94
  }
92
95
  }
93
96
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aidriftline/driftline",
3
- "version": "0.1.10",
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",
@@ -1033,7 +1033,7 @@
1033
1033
  "provider": "openai",
1034
1034
  "retires": "2027-02-26",
1035
1035
  "qualifier": "exact",
1036
- "replacement": "gpt-transcribe",
1036
+ "replacement": "gpt-live-transcribe",
1037
1037
  "kind": "audio"
1038
1038
  },
1039
1039
  {
@@ -1041,7 +1041,7 @@
1041
1041
  "provider": "openai",
1042
1042
  "retires": "2027-02-26",
1043
1043
  "qualifier": "exact",
1044
- "replacement": "gpt-transcribe",
1044
+ "replacement": "gpt-live-transcribe",
1045
1045
  "kind": "audio"
1046
1046
  },
1047
1047
  {
@@ -1049,7 +1049,7 @@
1049
1049
  "provider": "openai",
1050
1050
  "retires": "2027-02-26",
1051
1051
  "qualifier": "exact",
1052
- "replacement": "gpt-transcribe",
1052
+ "replacement": "gpt-live-transcribe",
1053
1053
  "kind": "audio"
1054
1054
  },
1055
1055
  {
@@ -1057,7 +1057,7 @@
1057
1057
  "provider": "openai",
1058
1058
  "retires": "2027-02-26",
1059
1059
  "qualifier": "exact",
1060
- "replacement": "gpt-transcribe",
1060
+ "replacement": "gpt-live-transcribe",
1061
1061
  "kind": "audio"
1062
1062
  },
1063
1063
  {
@@ -1065,7 +1065,7 @@
1065
1065
  "provider": "openai",
1066
1066
  "retires": "2027-02-26",
1067
1067
  "qualifier": "exact",
1068
- "replacement": "gpt-transcribe",
1068
+ "replacement": "gpt-live-transcribe",
1069
1069
  "kind": "audio"
1070
1070
  },
1071
1071
  {
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;