@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 +10 -7
- package/package.json +1 -1
- package/registry/models.json +5 -5
- package/src/cli.js +4 -4
- package/src/mcp.js +12 -2
- package/src/run.js +1 -1
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
|
|
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
|
|
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
|
|
66
|
-
npx
|
|
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
|
|
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
|
+
[](https://cursor.com/en/install-mcp?name=driftline&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBhaWRyaWZ0bGluZS9kcmlmdGxpbmUiLCJtY3AiXX0%3D)
|
|
80
|
+
[](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
|
|
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", "
|
|
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.
|
|
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/registry/models.json
CHANGED
|
@@ -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
|
|
32
|
-
npx
|
|
33
|
-
npx
|
|
34
|
-
npx
|
|
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
|
-
|
|
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(`
|
|
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;
|