@namzu/cli 8.1.0 → 8.2.0

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.
@@ -25,7 +25,28 @@
25
25
  * package has no component tests and a secret is the worst thing to leave
26
26
  * unverifiable.
27
27
  */
28
- import type { DetectedProvider, ProviderRegistryEntry } from '../integrations/providers/index.js';
28
+ import { type DetectedProvider, type ProviderRegistryEntry } from '../integrations/providers/index.js';
29
+ /**
30
+ * Which kind of secret was pasted.
31
+ *
32
+ * The distinction is not cosmetic: the two travel differently on the wire —
33
+ * `constructProvider` sends one as `authToken` and the other as `apiKey` — and
34
+ * they expire differently. A subscription token is short-lived and is renewed
35
+ * from refresh metadata that only the discovered credential carries; a hand
36
+ * pasted one has none, so it lapses in hours with nothing to renew it. An
37
+ * operator who is not told that at the moment they paste discovers it as a 401
38
+ * mid-turn, which is the difference between a feature and a trap.
39
+ */
40
+ export type CredentialKind = 'api-key' | 'subscription-token';
41
+ /**
42
+ * Classify a pasted secret by its own shape.
43
+ *
44
+ * Reuses the classifier the session layer already decides the wire header with
45
+ * (`isAnthropicOAuthToken`), so the screen cannot say one thing while the
46
+ * request says another. Every other provider takes an API key and nothing else,
47
+ * so asking the question of them would invent a distinction they do not have.
48
+ */
49
+ export declare function classifyCredential(entry: ProviderRegistryEntry, key: string): CredentialKind;
29
50
  /**
30
51
  * What a key looks like on screen. Never the key.
31
52
  *
@@ -64,18 +85,29 @@ export type Verification = {
64
85
  /**
65
86
  * What namzu tells the operator it did with what they typed.
66
87
  *
67
- * Every branch says three things: that it worked or did not, that the key is
68
- * held for this session only, and the environment variable that persists it.
69
- * The middle one is the part a person is most likely to assume otherwise —
70
- * typing a credential into an application usually means it was saved.
88
+ * Every branch says four things: that it worked or did not, WHICH KIND of
89
+ * credential it took, that it is held for this session only, and the
90
+ * environment variable that persists it. The third is the part a person is most
91
+ * likely to assume otherwise — typing a credential into an application usually
92
+ * means it was saved.
93
+ *
94
+ * The kind is said out loud because the two behave differently after this
95
+ * screen, and only one of them can be renewed. See {@link CredentialKind}.
71
96
  */
72
- export declare function describeDisposition(entry: ProviderRegistryEntry, verification: Verification): string;
97
+ export declare function describeDisposition(entry: ProviderRegistryEntry, verification: Verification, kind?: CredentialKind): string;
73
98
  /**
74
99
  * The detected-provider record a typed key produces.
75
100
  *
76
101
  * Shaped exactly like a discovered one so every downstream path — session
77
102
  * construction, the model picker, `/provider` — treats it identically. The only
78
103
  * difference is `source`, so a surface can say where it came from.
104
+ *
105
+ * `oauth` is deliberately NOT set, for a subscription token as much as for an
106
+ * API key. That field means "this credential can be renewed from a refresh
107
+ * token", the session layer gates its refresh on it, and a hand-pasted token
108
+ * supplies no refresh token — so filling it in would claim a renewal path that
109
+ * does not exist and turn a disclosed expiry into a silent 401. The disclosure
110
+ * in `describeDisposition` is the substitute.
79
111
  */
80
112
  export declare function sessionCredential(entry: ProviderRegistryEntry, key: string): DetectedProvider;
81
113
  //# sourceMappingURL=credential-entry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"credential-entry.d.ts","sourceRoot":"","sources":["../../src/tui/credential-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAEjG;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAexF;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE;AAC/B,oEAAoE;GAClE;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACjC;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,qBAAqB,EAC5B,YAAY,EAAE,YAAY,GACxB,MAAM,CAuBR;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAQ7F"}
1
+ {"version":3,"file":"credential-entry.d.ts","sourceRoot":"","sources":["../../src/tui/credential-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAE1B,MAAM,oCAAoC,CAAA;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,oBAAoB,CAAA;AAE7D;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAG5F;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAmBxF;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE;AAC/B,oEAAoE;GAClE;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACjC;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,qBAAqB,EAC5B,YAAY,EAAE,YAAY,EAC1B,IAAI,GAAE,cAA0B,GAC9B,MAAM,CAmCR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAQ7F"}
@@ -25,6 +25,20 @@
25
25
  * package has no component tests and a secret is the worst thing to leave
26
26
  * unverifiable.
27
27
  */
28
+ import { isAnthropicOAuthToken, } from '../integrations/providers/index.js';
29
+ /**
30
+ * Classify a pasted secret by its own shape.
31
+ *
32
+ * Reuses the classifier the session layer already decides the wire header with
33
+ * (`isAnthropicOAuthToken`), so the screen cannot say one thing while the
34
+ * request says another. Every other provider takes an API key and nothing else,
35
+ * so asking the question of them would invent a distinction they do not have.
36
+ */
37
+ export function classifyCredential(entry, key) {
38
+ if (entry.id !== 'anthropic')
39
+ return 'api-key';
40
+ return isAnthropicOAuthToken(key.trim()) ? 'subscription-token' : 'api-key';
41
+ }
28
42
  /**
29
43
  * What a key looks like on screen. Never the key.
30
44
  *
@@ -56,11 +70,15 @@ export function keyLooksUsable(key) {
56
70
  if (/\s/.test(trimmed)) {
57
71
  return { ok: false, reason: 'That contains a space — check for a truncated or wrapped paste.' };
58
72
  }
59
- if (trimmed.startsWith('$') || trimmed.includes('=')) {
73
+ // Assignment-SHAPED, not "contains an equals sign". The old test rejected any
74
+ // `=` anywhere, which is fine for an API key and wrong for a subscription
75
+ // token: a JWT-shaped one is base64 and may carry `=` padding, so the screen
76
+ // refused a valid credential and blamed the operator's paste for it. This
77
+ // still catches the case the check exists for — `ANTHROPIC_API_KEY=sk-…`
78
+ // copied out of a shell profile — because that has a variable name in front.
79
+ if (trimmed.startsWith('$') || /^[A-Za-z_][A-Za-z0-9_]*=/.test(trimmed)) {
60
80
  return {
61
81
  ok: false,
62
- // The classic: pasting `ANTHROPIC_API_KEY=sk-…` or `$MY_KEY` from a
63
- // shell profile rather than the value.
64
82
  reason: 'That looks like a shell assignment or variable. Paste the key itself.',
65
83
  };
66
84
  }
@@ -69,21 +87,26 @@ export function keyLooksUsable(key) {
69
87
  /**
70
88
  * What namzu tells the operator it did with what they typed.
71
89
  *
72
- * Every branch says three things: that it worked or did not, that the key is
73
- * held for this session only, and the environment variable that persists it.
74
- * The middle one is the part a person is most likely to assume otherwise —
75
- * typing a credential into an application usually means it was saved.
90
+ * Every branch says four things: that it worked or did not, WHICH KIND of
91
+ * credential it took, that it is held for this session only, and the
92
+ * environment variable that persists it. The third is the part a person is most
93
+ * likely to assume otherwise — typing a credential into an application usually
94
+ * means it was saved.
95
+ *
96
+ * The kind is said out loud because the two behave differently after this
97
+ * screen, and only one of them can be renewed. See {@link CredentialKind}.
76
98
  */
77
- export function describeDisposition(entry, verification) {
99
+ export function describeDisposition(entry, verification, kind = 'api-key') {
100
+ const noun = kind === 'subscription-token' ? 'subscription token' : 'API key';
78
101
  const persist = entry.envVars[0];
79
102
  const durable = persist
80
103
  ? `To keep it, set ${persist} in your shell and restart.`
81
104
  : 'To keep it, configure the credential in your environment and restart.';
82
105
  if (verification.kind === 'rejected') {
83
- return `${entry.label} rejected that key: ${verification.reason}\nNothing was stored.`;
106
+ return `${entry.label} rejected that ${noun}: ${verification.reason}\nNothing was stored.`;
84
107
  }
85
108
  const checked = verification.kind === 'verified'
86
- ? `${entry.label} accepted the key.`
109
+ ? `${entry.label} accepted the ${noun}.`
87
110
  : // Said plainly rather than implied. Claiming a key is good would be
88
111
  // inventing a verification that did not happen — and this now covers
89
112
  // two ways of not happening: a driver that declares no credential
@@ -91,8 +114,17 @@ export function describeDisposition(entry, verification) {
91
114
  // wording asserted the first ("offers no way to check it"), which
92
115
  // would be false for a probe that timed out. Neither is a bad key,
93
116
  // and neither is a checked one.
94
- `Key accepted, but NOT checked — ${entry.label} could not confirm it just now, so the first message will be the test.`;
95
- return `${checked}\nHeld in memory for this session only — it is not written anywhere. ${durable}`;
117
+ `${noun.replace(/^./, (c) => c.toUpperCase())} accepted, but NOT checked — ${entry.label} could not confirm it just now, so the first message will be the test.`;
118
+ // Disclosed HERE, at the paste, and not left to be discovered as a 401 in the
119
+ // middle of a turn. A discovered subscription token arrives with a refresh
120
+ // token and an expiry, and the session layer renews it between turns; a
121
+ // pasted one carries neither, so there is nothing to renew it with. Saying
122
+ // "it lasts hours" is the honest form of a limitation we cannot remove
123
+ // without an authorization flow namzu does not have.
124
+ const expiry = kind === 'subscription-token'
125
+ ? '\nA pasted subscription token has no refresh data with it, so it expires in a few hours and namzu cannot renew it — expect to enter it again.'
126
+ : '';
127
+ return `${checked}\nHeld in memory for this session only — it is not written anywhere. ${durable}${expiry}`;
96
128
  }
97
129
  /**
98
130
  * The detected-provider record a typed key produces.
@@ -100,6 +132,13 @@ export function describeDisposition(entry, verification) {
100
132
  * Shaped exactly like a discovered one so every downstream path — session
101
133
  * construction, the model picker, `/provider` — treats it identically. The only
102
134
  * difference is `source`, so a surface can say where it came from.
135
+ *
136
+ * `oauth` is deliberately NOT set, for a subscription token as much as for an
137
+ * API key. That field means "this credential can be renewed from a refresh
138
+ * token", the session layer gates its refresh on it, and a hand-pasted token
139
+ * supplies no refresh token — so filling it in would claim a renewal path that
140
+ * does not exist and turn a disclosed expiry into a silent 401. The disclosure
141
+ * in `describeDisposition` is the substitute.
103
142
  */
104
143
  export function sessionCredential(entry, key) {
105
144
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"credential-entry.js","sourceRoot":"","sources":["../../src/tui/credential-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW;IAClC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IAC1B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9B,OAAO,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAA;AACxD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACzC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IAC1B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAA;IACzE,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iEAAiE,EAAE,CAAA;IAChG,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,OAAO;YACN,EAAE,EAAE,KAAK;YACT,oEAAoE;YACpE,uCAAuC;YACvC,MAAM,EAAE,uEAAuE;SAC/E,CAAA;IACF,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;AACpB,CAAC;AASD;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAClC,KAA4B,EAC5B,YAA0B;IAE1B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAChC,MAAM,OAAO,GAAG,OAAO;QACtB,CAAC,CAAC,mBAAmB,OAAO,6BAA6B;QACzD,CAAC,CAAC,uEAAuE,CAAA;IAE1E,IAAI,YAAY,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACtC,OAAO,GAAG,KAAK,CAAC,KAAK,uBAAuB,YAAY,CAAC,MAAM,uBAAuB,CAAA;IACvF,CAAC;IAED,MAAM,OAAO,GACZ,YAAY,CAAC,IAAI,KAAK,UAAU;QAC/B,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,oBAAoB;QACpC,CAAC,CAAC,oEAAoE;YACrE,qEAAqE;YACrE,kEAAkE;YAClE,kEAAkE;YAClE,kEAAkE;YAClE,mEAAmE;YACnE,gCAAgC;YAChC,mCAAmC,KAAK,CAAC,KAAK,wEAAwE,CAAA;IAEzH,OAAO,GAAG,OAAO,wEAAwE,OAAO,EAAE,CAAA;AACnG,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA4B,EAAE,GAAW;IAC1E,OAAO;QACN,KAAK;QACL,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAC3B,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE;QAClB,GAAG,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,YAAY,EAAE,EAAE;KAChB,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"credential-entry.js","sourceRoot":"","sources":["../../src/tui/credential-entry.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/cli",
3
- "version": "8.1.0",
3
+ "version": "8.2.0",
4
4
  "description": "Operator CLI for the Namzu agent platform — namzu doctor + future commands. Dual-purpose: standalone bin (`namzu doctor`) and library (`import { runDoctor } from '@namzu/cli'`).",
5
5
  "keywords": [
6
6
  "namzu",
@@ -44,11 +44,11 @@
44
44
  "ink": "^7.0.3",
45
45
  "react": "^19.2.6",
46
46
  "yaml": "^2.9.0",
47
- "@namzu/ollama": "2.1.0",
47
+ "@namzu/anthropic": "3.2.0",
48
48
  "@namzu/openai": "1.2.0",
49
49
  "@namzu/sdk": "^21.1.0",
50
50
  "@namzu/openrouter": "2.1.0",
51
- "@namzu/anthropic": "3.2.0"
51
+ "@namzu/ollama": "2.1.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@biomejs/biome": "^1.9.4",