@namzu/cli 2.6.1 → 4.0.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.
Files changed (55) hide show
  1. package/dist/commands/doctor.d.ts.map +1 -1
  2. package/dist/commands/doctor.js +15 -4
  3. package/dist/commands/doctor.js.map +1 -1
  4. package/dist/commands/run-flags.d.ts +23 -0
  5. package/dist/commands/run-flags.d.ts.map +1 -1
  6. package/dist/commands/run-flags.js +39 -0
  7. package/dist/commands/run-flags.js.map +1 -1
  8. package/dist/commands/run-stream.d.ts.map +1 -1
  9. package/dist/commands/run-stream.js +12 -6
  10. package/dist/commands/run-stream.js.map +1 -1
  11. package/dist/commands/run.d.ts.map +1 -1
  12. package/dist/commands/run.js +12 -6
  13. package/dist/commands/run.js.map +1 -1
  14. package/dist/doctor/checks/chain.d.ts +32 -0
  15. package/dist/doctor/checks/chain.d.ts.map +1 -0
  16. package/dist/doctor/checks/chain.js +118 -0
  17. package/dist/doctor/checks/chain.js.map +1 -0
  18. package/dist/doctor/checks/index.d.ts +2 -1
  19. package/dist/doctor/checks/index.d.ts.map +1 -1
  20. package/dist/doctor/checks/index.js +6 -1
  21. package/dist/doctor/checks/index.js.map +1 -1
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/integrations/providers/chain-capabilities.d.ts +80 -0
  27. package/dist/integrations/providers/chain-capabilities.d.ts.map +1 -0
  28. package/dist/integrations/providers/chain-capabilities.js +207 -0
  29. package/dist/integrations/providers/chain-capabilities.js.map +1 -0
  30. package/dist/integrations/providers/index.d.ts +2 -1
  31. package/dist/integrations/providers/index.d.ts.map +1 -1
  32. package/dist/integrations/providers/index.js +2 -1
  33. package/dist/integrations/providers/index.js.map +1 -1
  34. package/dist/integrations/providers/preferences.d.ts +84 -15
  35. package/dist/integrations/providers/preferences.d.ts.map +1 -1
  36. package/dist/integrations/providers/preferences.js +180 -25
  37. package/dist/integrations/providers/preferences.js.map +1 -1
  38. package/dist/tui/App.d.ts.map +1 -1
  39. package/dist/tui/App.js +92 -16
  40. package/dist/tui/App.js.map +1 -1
  41. package/dist/tui/PermissionOverlay.d.ts.map +1 -1
  42. package/dist/tui/PermissionOverlay.js +1 -1
  43. package/dist/tui/PermissionOverlay.js.map +1 -1
  44. package/dist/tui/TrustPrompt.d.ts.map +1 -1
  45. package/dist/tui/TrustPrompt.js +1 -1
  46. package/dist/tui/TrustPrompt.js.map +1 -1
  47. package/dist/tui/agent.d.ts +12 -0
  48. package/dist/tui/agent.d.ts.map +1 -1
  49. package/dist/tui/agent.js +70 -10
  50. package/dist/tui/agent.js.map +1 -1
  51. package/dist/tui/consent-timing.d.ts +44 -0
  52. package/dist/tui/consent-timing.d.ts.map +1 -0
  53. package/dist/tui/consent-timing.js +48 -0
  54. package/dist/tui/consent-timing.js.map +1 -0
  55. package/package.json +3 -3
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  export { createDoctorRegistry, doctor, DoctorRegistry, registerDoctorCheck, runDoctor, } from './doctor/registry.js';
7
7
  export type { RunDoctorOptions } from './doctor/registry.js';
8
- export { builtInDoctorChecks, credentialSourcesCheck, cwdWritableCheck, providersRegisteredCheck, sandboxPlatformCheck, telemetryInstalledCheck, tmpdirWritableCheck, vaultRegisteredCheck, } from './doctor/checks/index.js';
8
+ export { builtInDoctorChecks, credentialSourcesCheck, cwdWritableCheck, providerChainCheck, providersRegisteredCheck, sandboxPlatformCheck, telemetryInstalledCheck, tmpdirWritableCheck, vaultRegisteredCheck, } from './doctor/checks/index.js';
9
9
  export { runDoctorCommand } from './commands/doctor.js';
10
10
  export { runCli, type RunCliOptions } from './cli.js';
11
11
  export type { CommandContext, CommandDef, CommandHandler, CommandHandlerArgs, } from './commands/types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACN,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,SAAS,GACT,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,OAAO,EACN,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAA;AACrD,YAAY,EACX,cAAc,EACd,UAAU,EACV,cAAc,EACd,kBAAkB,GAClB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACN,WAAW,EACX,eAAe,EACf,KAAK,eAAe,GACpB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACN,eAAe,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,YAAY,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACN,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,SAAS,GACT,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,OAAO,EACN,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAA;AACrD,YAAY,EACX,cAAc,EACd,UAAU,EACV,cAAc,EACd,kBAAkB,GAClB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACN,WAAW,EACX,eAAe,EACf,KAAK,eAAe,GACpB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACN,eAAe,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,YAAY,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  // Doctor library API (pre-M0; preserved for embedded consumers).
7
7
  export { createDoctorRegistry, doctor, DoctorRegistry, registerDoctorCheck, runDoctor, } from './doctor/registry.js';
8
- export { builtInDoctorChecks, credentialSourcesCheck, cwdWritableCheck, providersRegisteredCheck, sandboxPlatformCheck, telemetryInstalledCheck, tmpdirWritableCheck, vaultRegisteredCheck, } from './doctor/checks/index.js';
8
+ export { builtInDoctorChecks, credentialSourcesCheck, cwdWritableCheck, providerChainCheck, providersRegisteredCheck, sandboxPlatformCheck, telemetryInstalledCheck, tmpdirWritableCheck, vaultRegisteredCheck, } from './doctor/checks/index.js';
9
9
  export { runDoctorCommand } from './commands/doctor.js';
10
10
  // Shell + extension surface for the CLI.
11
11
  export { runCli } from './cli.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,iEAAiE;AACjE,OAAO,EACN,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,SAAS,GACT,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACN,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD,yCAAyC;AACzC,OAAO,EAAE,MAAM,EAAsB,MAAM,UAAU,CAAA;AAOrD,OAAO,EACN,WAAW,EACX,eAAe,GAEf,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACN,eAAe,EAIf,YAAY,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,UAAU,EAA0B,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAE,cAAc,EAAuB,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,iEAAiE;AACjE,OAAO,EACN,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,SAAS,GACT,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACN,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD,yCAAyC;AACzC,OAAO,EAAE,MAAM,EAAsB,MAAM,UAAU,CAAA;AAOrD,OAAO,EACN,WAAW,EACX,eAAe,GAEf,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACN,eAAe,EAIf,YAAY,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,UAAU,EAA0B,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAE,cAAc,EAAuB,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Do the members of a provider chain agree about what they can do?
3
+ *
4
+ * The runtime negotiates capabilities ONCE per run, against the provider it was
5
+ * handed, and that answer decides whether tool surfaces go into the prompt and
6
+ * whether image and document attachments are mapped. A chain whose members
7
+ * disagree therefore cannot be honoured by taking the strongest answer: if the
8
+ * run falls over to a weaker member it arrives holding a request shaped for a
9
+ * provider that is no longer serving it — tools advertised that cannot be
10
+ * called, images the driver will not map.
11
+ *
12
+ * The alternative to refusing is intersecting: quietly take the floor of the
13
+ * chain. That is worse, and worse in the direction that matters. An operator who
14
+ * adds a weaker fallback to gain resilience would find their PRIMARY had quietly
15
+ * lost tool support, permanently, with nothing saying so — a capability given up
16
+ * on every run to guard against a failure that happens rarely. So a disagreement
17
+ * is refused and named, and an operator who wants the intersection anyway says
18
+ * so explicitly.
19
+ *
20
+ * ## This compares DECLARATIONS, and says only that
21
+ *
22
+ * What is compared is what each driver declares at the type level, which is the
23
+ * only thing knowable before a provider is constructed — and constructing one
24
+ * would need a credential, which is exactly what a not-yet-configured fallback
25
+ * does not have. The runtime treats the constructed INSTANCE's own declaration
26
+ * as authoritative, so an instance can in principle disagree with its type.
27
+ * Every sentence here therefore says "declares" rather than asserting what a
28
+ * provider IS. A check that overstates its authority is how someone later finds
29
+ * the runtime disagreed with it and stops believing it.
30
+ *
31
+ * ## And it is a property of the CHAIN, not of a run
32
+ *
33
+ * Only the primary runs today; nothing falls over yet. So no sentence here
34
+ * claims a run is degraded — each says what becomes unavailable IF the chain
35
+ * falls over. When failover lands the run-level statement becomes true and can
36
+ * be made then. Making it now would be a confident claim about a degradation
37
+ * that has not happened, which is the failure this line of work exists to
38
+ * remove.
39
+ */
40
+ import type { ResolvedProviderCapabilities } from '@namzu/sdk';
41
+ import { type ProviderChoice } from './preferences.js';
42
+ /** A member paired with what it declares, or with why that could not be read. */
43
+ export type MemberCapabilities = {
44
+ readonly kind: 'known';
45
+ readonly capabilities: ResolvedProviderCapabilities;
46
+ } | {
47
+ readonly kind: 'unresolved';
48
+ readonly reason: string;
49
+ };
50
+ export interface CapabilityDisagreement {
51
+ /** Index of the member that declares the capability. */
52
+ readonly declaredBy: number;
53
+ /** Index of the member that declares it does not have it. */
54
+ readonly missingFrom: number;
55
+ /** One sentence naming both members and what is lost. */
56
+ readonly sentence: string;
57
+ }
58
+ /**
59
+ * Every way the members of this chain declare different abilities.
60
+ *
61
+ * A disagreement is reported against the FIRST member that declares the
62
+ * capability, because that is the behaviour the operator already has and would
63
+ * be surprised to lose. Members whose capabilities could not be read contribute
64
+ * nothing: an unestablished answer is not agreement, and counting it as one
65
+ * would turn "I could not check this" into "this is fine".
66
+ */
67
+ export declare function chainCapabilityDisagreements(members: readonly ProviderChoice[], resolved: readonly MemberCapabilities[]): readonly CapabilityDisagreement[];
68
+ /** Members whose declarations could not be established, with the reason. */
69
+ export declare function unresolvedMembers(members: readonly ProviderChoice[], resolved: readonly MemberCapabilities[]): readonly string[];
70
+ /**
71
+ * The refusal an operator reads, or null when the chain agrees.
72
+ *
73
+ * Every disagreement is named, not just the first: an operator who fixes the one
74
+ * sentence they were shown and is refused again for the next has been made to
75
+ * discover their own configuration one round-trip at a time.
76
+ */
77
+ export declare function describeCapabilityRefusal(disagreements: readonly CapabilityDisagreement[]): string | null;
78
+ /** The same disagreements, worded for an operator who has already accepted them. */
79
+ export declare function describeAcceptedMismatch(disagreements: readonly CapabilityDisagreement[]): string | null;
80
+ //# sourceMappingURL=chain-capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-capabilities.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/chain-capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAE9D,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,kBAAkB,CAAA;AAGzE,iFAAiF;AACjF,MAAM,MAAM,kBAAkB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,4BAA4B,CAAA;CAAE,GAC/E;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3D,MAAM,WAAW,sBAAsB;IACtC,wDAAwD;IACxD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CACzB;AA0DD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GACrC,SAAS,sBAAsB,EAAE,CA6BnC;AA+CD,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GACrC,SAAS,MAAM,EAAE,CAQnB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACxC,aAAa,EAAE,SAAS,sBAAsB,EAAE,GAC9C,MAAM,GAAG,IAAI,CASf;AAED,oFAAoF;AACpF,wBAAgB,wBAAwB,CACvC,aAAa,EAAE,SAAS,sBAAsB,EAAE,GAC9C,MAAM,GAAG,IAAI,CAMf"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Do the members of a provider chain agree about what they can do?
3
+ *
4
+ * The runtime negotiates capabilities ONCE per run, against the provider it was
5
+ * handed, and that answer decides whether tool surfaces go into the prompt and
6
+ * whether image and document attachments are mapped. A chain whose members
7
+ * disagree therefore cannot be honoured by taking the strongest answer: if the
8
+ * run falls over to a weaker member it arrives holding a request shaped for a
9
+ * provider that is no longer serving it — tools advertised that cannot be
10
+ * called, images the driver will not map.
11
+ *
12
+ * The alternative to refusing is intersecting: quietly take the floor of the
13
+ * chain. That is worse, and worse in the direction that matters. An operator who
14
+ * adds a weaker fallback to gain resilience would find their PRIMARY had quietly
15
+ * lost tool support, permanently, with nothing saying so — a capability given up
16
+ * on every run to guard against a failure that happens rarely. So a disagreement
17
+ * is refused and named, and an operator who wants the intersection anyway says
18
+ * so explicitly.
19
+ *
20
+ * ## This compares DECLARATIONS, and says only that
21
+ *
22
+ * What is compared is what each driver declares at the type level, which is the
23
+ * only thing knowable before a provider is constructed — and constructing one
24
+ * would need a credential, which is exactly what a not-yet-configured fallback
25
+ * does not have. The runtime treats the constructed INSTANCE's own declaration
26
+ * as authoritative, so an instance can in principle disagree with its type.
27
+ * Every sentence here therefore says "declares" rather than asserting what a
28
+ * provider IS. A check that overstates its authority is how someone later finds
29
+ * the runtime disagreed with it and stops believing it.
30
+ *
31
+ * ## And it is a property of the CHAIN, not of a run
32
+ *
33
+ * Only the primary runs today; nothing falls over yet. So no sentence here
34
+ * claims a run is degraded — each says what becomes unavailable IF the chain
35
+ * falls over. When failover lands the run-level statement becomes true and can
36
+ * be made then. Making it now would be a confident claim about a degradation
37
+ * that has not happened, which is the failure this line of work exists to
38
+ * remove.
39
+ */
40
+ import { chainPositionName } from './preferences.js';
41
+ import { PROVIDER_REGISTRY } from './registry.js';
42
+ /**
43
+ * The boolean capabilities, with the words for having one, lacking it, and
44
+ * losing it.
45
+ *
46
+ * `supportsStreaming` is here even though every shipped driver declares it. The
47
+ * field exists and a third-party driver may not have it; leaving it out would
48
+ * let a chain disagree on it and pass.
49
+ */
50
+ const BOOLEAN_CAPABILITIES = [
51
+ {
52
+ key: 'supportsTools',
53
+ has: 'it can call tools',
54
+ lacks: 'it cannot call tools',
55
+ consequence: 'tools become unavailable',
56
+ },
57
+ {
58
+ key: 'supportsFunctionCalling',
59
+ has: 'it supports function calling',
60
+ lacks: 'it does not support function calling',
61
+ consequence: 'function calling becomes unavailable',
62
+ },
63
+ {
64
+ key: 'supportsStreaming',
65
+ has: 'it can stream replies',
66
+ lacks: 'it cannot stream replies',
67
+ consequence: 'replies stop streaming',
68
+ },
69
+ {
70
+ key: 'supportsVision',
71
+ has: 'it can read image attachments',
72
+ lacks: 'it cannot read image attachments',
73
+ consequence: 'image attachments stop being sent',
74
+ },
75
+ {
76
+ key: 'supportsDocuments',
77
+ has: 'it can read document attachments',
78
+ lacks: 'it cannot read document attachments',
79
+ consequence: 'document attachments stop being sent',
80
+ },
81
+ ];
82
+ function describe(index, member) {
83
+ const entry = PROVIDER_REGISTRY[member.id];
84
+ return `${chainPositionName(index)} (${entry ? entry.label : member.id})`;
85
+ }
86
+ /**
87
+ * Every way the members of this chain declare different abilities.
88
+ *
89
+ * A disagreement is reported against the FIRST member that declares the
90
+ * capability, because that is the behaviour the operator already has and would
91
+ * be surprised to lose. Members whose capabilities could not be read contribute
92
+ * nothing: an unestablished answer is not agreement, and counting it as one
93
+ * would turn "I could not check this" into "this is fine".
94
+ */
95
+ export function chainCapabilityDisagreements(members, resolved) {
96
+ const out = [];
97
+ for (const capability of BOOLEAN_CAPABILITIES) {
98
+ const firstWithIt = resolved.findIndex((entry) => entry.kind === 'known' && entry.capabilities[capability.key] === true);
99
+ if (firstWithIt === -1)
100
+ continue;
101
+ const has = members[firstWithIt];
102
+ if (!has)
103
+ continue;
104
+ for (const [index, entry] of resolved.entries()) {
105
+ if (entry.kind !== 'known' || index === firstWithIt)
106
+ continue;
107
+ if (entry.capabilities[capability.key] === true)
108
+ continue;
109
+ const lacks = members[index];
110
+ if (!lacks)
111
+ continue;
112
+ out.push({
113
+ declaredBy: firstWithIt,
114
+ missingFrom: index,
115
+ sentence: `${describe(index, lacks)} declares ${capability.lacks}, while ` +
116
+ `${describe(firstWithIt, has)} declares ${capability.has} — ` +
117
+ `if the chain falls over to it, ${capability.consequence}.`,
118
+ });
119
+ }
120
+ }
121
+ out.push(...ceilingDisagreements(members, resolved));
122
+ return out;
123
+ }
124
+ /**
125
+ * A smaller output ceiling is the same problem wearing a number: a run served by
126
+ * that member produces shorter replies than the chain was configured for.
127
+ * Reported against the LARGEST declared ceiling, for the reason the booleans are
128
+ * reported against the first member that has the capability.
129
+ */
130
+ function ceilingDisagreements(members, resolved) {
131
+ const ceilings = [];
132
+ for (const [index, entry] of resolved.entries()) {
133
+ if (entry.kind !== 'known')
134
+ continue;
135
+ const value = entry.capabilities.maxOutputTokens;
136
+ if (typeof value === 'number')
137
+ ceilings.push({ index, value });
138
+ }
139
+ // No `length < 2` guard: a lone ceiling is already handled below, because it
140
+ // IS the largest and the comparison skips it. Adding one would be a branch
141
+ // that cannot change the answer, which is a check that cannot fail
142
+ // (`docs/conventions/a-check-that-cannot-fail.md`) — and a mutation proving
143
+ // exactly that is how this one was found.
144
+ let largest;
145
+ for (const ceiling of ceilings) {
146
+ if (!largest || ceiling.value > largest.value)
147
+ largest = ceiling;
148
+ }
149
+ if (!largest)
150
+ return [];
151
+ const out = [];
152
+ for (const ceiling of ceilings) {
153
+ if (ceiling.value >= largest.value)
154
+ continue;
155
+ const has = members[largest.index];
156
+ const lacks = members[ceiling.index];
157
+ if (!has || !lacks)
158
+ continue;
159
+ out.push({
160
+ declaredBy: largest.index,
161
+ missingFrom: ceiling.index,
162
+ sentence: `${describe(ceiling.index, lacks)} declares a maximum output of ${ceiling.value} tokens, ` +
163
+ `below ${describe(largest.index, has)} at ${largest.value} — ` +
164
+ `if the chain falls over to it, replies are capped at ${ceiling.value}.`,
165
+ });
166
+ }
167
+ return out;
168
+ }
169
+ /** Members whose declarations could not be established, with the reason. */
170
+ export function unresolvedMembers(members, resolved) {
171
+ const out = [];
172
+ for (const [index, entry] of resolved.entries()) {
173
+ const member = members[index];
174
+ if (entry.kind !== 'unresolved' || !member)
175
+ continue;
176
+ out.push(`${describe(index, member)}: ${entry.reason}`);
177
+ }
178
+ return out;
179
+ }
180
+ /**
181
+ * The refusal an operator reads, or null when the chain agrees.
182
+ *
183
+ * Every disagreement is named, not just the first: an operator who fixes the one
184
+ * sentence they were shown and is refused again for the next has been made to
185
+ * discover their own configuration one round-trip at a time.
186
+ */
187
+ export function describeCapabilityRefusal(disagreements) {
188
+ if (disagreements.length === 0)
189
+ return null;
190
+ return [
191
+ 'The providers in your chain declare different capabilities, so namzu cannot honour the chain as written:',
192
+ ...disagreements.map((d) => ` - ${d.sentence}`),
193
+ '',
194
+ 'Taking the strongest answer would advertise abilities a fallback does not have. Taking the weakest would cost your primary a capability on every run, to guard against a failure that happens rarely. Neither is chosen for you.',
195
+ 'Either drop the member that disagrees, or set "allowCapabilityMismatch": true in ~/.namzu/preferences.json to accept the limitation — it is printed on every launch.',
196
+ ].join('\n');
197
+ }
198
+ /** The same disagreements, worded for an operator who has already accepted them. */
199
+ export function describeAcceptedMismatch(disagreements) {
200
+ if (disagreements.length === 0)
201
+ return null;
202
+ return [
203
+ 'Provider chain: the members declare different capabilities, and you have accepted that.',
204
+ ...disagreements.map((d) => ` - ${d.sentence}`),
205
+ ].join('\n');
206
+ }
207
+ //# sourceMappingURL=chain-capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-capabilities.js","sourceRoot":"","sources":["../../../src/integrations/providers/chain-capabilities.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export { type DetectedProvider, type DetectionSource, type DiscoverOptions, discoverProviders, findDetected, } from './discover.js';
2
2
  export { type AgentOAuthCredential, isAnthropicOAuthToken, readAgentKeychainCredential, } from './keychain.js';
3
3
  export { ensureFreshAnthropicToken, type OAuthMetadata, refreshAgentOAuthToken, } from './oauth.js';
4
- export { type Preferences, PREFERENCES_FILE_VERSION, PreferencesError, preferencesPath, type ReadResult, readPreferences, writePreferences, } from './preferences.js';
4
+ export { type CapabilityDisagreement, chainCapabilityDisagreements, describeAcceptedMismatch, describeCapabilityRefusal, type MemberCapabilities, unresolvedMembers, } from './chain-capabilities.js';
5
+ export { chainPositionName, type Preferences, PREFERENCES_FILE_VERSION, PreferencesError, preferencesPath, primaryProvider, type ProviderChoice, type ReadResult, readPreferences, writePreferences, } from './preferences.js';
5
6
  export { ALL_PROVIDER_IDS, PROVIDER_REGISTRY, type ProviderId, type ProviderRegistryEntry, type SdkProviderType, } from './registry.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,iBAAiB,EACjB,YAAY,GACZ,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,2BAA2B,GAC3B,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,yBAAyB,EACzB,KAAK,aAAa,EAClB,sBAAsB,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EACN,KAAK,WAAW,EAChB,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,KAAK,UAAU,EACf,eAAe,EACf,gBAAgB,GAChB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,eAAe,GACpB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,iBAAiB,EACjB,YAAY,GACZ,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,2BAA2B,GAC3B,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,yBAAyB,EACzB,KAAK,aAAa,EAClB,sBAAsB,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EACN,KAAK,sBAAsB,EAC3B,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EACzB,KAAK,kBAAkB,EACvB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACN,iBAAiB,EACjB,KAAK,WAAW,EAChB,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,eAAe,EACf,gBAAgB,GAChB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,eAAe,GACpB,MAAM,eAAe,CAAA"}
@@ -1,6 +1,7 @@
1
1
  export { discoverProviders, findDetected, } from './discover.js';
2
2
  export { isAnthropicOAuthToken, readAgentKeychainCredential, } from './keychain.js';
3
3
  export { ensureFreshAnthropicToken, refreshAgentOAuthToken, } from './oauth.js';
4
- export { PREFERENCES_FILE_VERSION, PreferencesError, preferencesPath, readPreferences, writePreferences, } from './preferences.js';
4
+ export { chainCapabilityDisagreements, describeAcceptedMismatch, describeCapabilityRefusal, unresolvedMembers, } from './chain-capabilities.js';
5
+ export { chainPositionName, PREFERENCES_FILE_VERSION, PreferencesError, preferencesPath, primaryProvider, readPreferences, writePreferences, } from './preferences.js';
5
6
  export { ALL_PROVIDER_IDS, PROVIDER_REGISTRY, } from './registry.js';
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/integrations/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,iBAAiB,EACjB,YAAY,GACZ,MAAM,eAAe,CAAA;AACtB,OAAO,EAEN,qBAAqB,EACrB,2BAA2B,GAC3B,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,yBAAyB,EAEzB,sBAAsB,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EAEN,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EAEf,eAAe,EACf,gBAAgB,GAChB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACN,gBAAgB,EAChB,iBAAiB,GAIjB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/integrations/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,iBAAiB,EACjB,YAAY,GACZ,MAAM,eAAe,CAAA;AACtB,OAAO,EAEN,qBAAqB,EACrB,2BAA2B,GAC3B,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,yBAAyB,EAEzB,sBAAsB,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EAEN,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EAEzB,iBAAiB,GACjB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACN,iBAAiB,EAEjB,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,eAAe,EAGf,eAAe,EACf,gBAAgB,GAChB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACN,gBAAgB,EAChB,iBAAiB,GAIjB,MAAM,eAAe,CAAA"}
@@ -1,30 +1,91 @@
1
1
  /**
2
- * `~/.namzu/preferences.json` — the user's primary-chat picker selection.
2
+ * `~/.namzu/preferences.json` — the operator's provider chain.
3
3
  *
4
- * Schema (current = v2):
4
+ * Schema (current = v3):
5
5
  * {
6
- * "version": 2,
7
- * "provider": "anthropic", // ProviderId
8
- * "model": "claude-opus-4-7", // optional model override
6
+ * "version": 3,
7
+ * "providers": [ // ordered; index 0 is the primary
8
+ * { "id": "anthropic", "model": "claude-opus-4-7" },
9
+ * { "id": "openai" } // model omitted → the registry default
10
+ * ],
9
11
  * "subagents": { "active": [...] } // instances reserved for subagent dispatch
10
12
  * }
11
13
  *
12
- * The previous schema (v1) stored a peer instance as the
13
- * default — a different primitive (subagent dispatch, not primary
14
- * chat). On-disk v1 files trigger a forced re-pick rather than an
15
- * auto-migration: mapping between the two semantics would surprise
16
- * more than help.
14
+ * The chain is an ORDER the operator declares, replacing the single provider v2
15
+ * held. It is deliberately a plain readable array in a file the operator owns:
16
+ * the order has to be legible and editable without launching the TUI, which a
17
+ * value only reachable through an interactive picker is not.
18
+ *
19
+ * **Only `providers[0]` runs today.** The rest are validated and reported (see
20
+ * `readPreferences` and the `providers.chain` doctor check) but nothing falls
21
+ * over to them yet. That is the point of shipping this first: a chain you can
22
+ * declare, read back, and have checked is useful before failover exists, and it
23
+ * is what failover will consume.
24
+ *
25
+ * ## Versions
26
+ *
27
+ * v1 stored a peer instance as the default — a different primitive (subagent
28
+ * dispatch, not primary chat). It is still REFUSED rather than migrated, because
29
+ * mapping between the two semantics would surprise more than help.
30
+ *
31
+ * v2 stored a single `provider` + optional `model`. It IS migrated, on read, in
32
+ * memory: one provider is a one-element chain, which is unambiguous, and the
33
+ * distinction from v1 is exactly that. Migration does not rewrite the file — a
34
+ * reader with a write side effect would rewrite `$HOME` on a `--help`. The next
35
+ * `writePreferences` lands v3.
36
+ *
37
+ * Note the consequence: a v3 file read by an older namzu reports `needs-repick`
38
+ * rather than silently losing the tail, which is the safe direction.
17
39
  */
18
- import type { ProviderId } from './registry.js';
19
- export declare const PREFERENCES_FILE_VERSION: 2;
20
- export interface Preferences {
21
- readonly version: 2;
22
- readonly provider: ProviderId;
40
+ import { type ProviderId } from './registry.js';
41
+ export declare const PREFERENCES_FILE_VERSION: 3;
42
+ /**
43
+ * One member of the provider chain.
44
+ *
45
+ * `model` omitted means the registry default for that provider, resolved at
46
+ * construction rather than stored — so a member does not pin itself to whatever
47
+ * the default happened to be on the day it was written.
48
+ */
49
+ export interface ProviderChoice {
50
+ readonly id: ProviderId;
23
51
  readonly model?: string;
52
+ }
53
+ export interface Preferences {
54
+ readonly version: 3;
55
+ /**
56
+ * The chain, in the operator's declared order. Index 0 is the primary and is
57
+ * the one that runs. Never empty — an empty chain is refused at read and at
58
+ * write, because it describes a namzu that cannot call anything while
59
+ * looking like a configured one.
60
+ */
61
+ readonly providers: readonly ProviderChoice[];
62
+ /**
63
+ * The operator has accepted a chain whose members declare different
64
+ * capabilities.
65
+ *
66
+ * Absent (the default), such a chain is REFUSED with the disagreement named.
67
+ * Taking the strongest declaration would advertise abilities a fallback does
68
+ * not have; taking the weakest would cost the primary a capability on every
69
+ * run to guard against a rare failure. Neither is chosen on the operator's
70
+ * behalf.
71
+ *
72
+ * Set, the chain runs and the disagreement is printed on every launch — not
73
+ * once. An acceptance given once and then forgotten is how a silent
74
+ * degradation comes back through the front door.
75
+ */
76
+ readonly allowCapabilityMismatch?: boolean;
24
77
  readonly subagents?: {
25
78
  readonly active: readonly string[];
26
79
  };
27
80
  }
81
+ /**
82
+ * How a member is named to the operator, by position.
83
+ *
84
+ * One function because three surfaces say it — validation, the doctor listing
85
+ * and the capability refusal — and a chain member called `fallback #1` in one
86
+ * message and `fallback 1` in the next reads as two different things.
87
+ */
88
+ export declare function chainPositionName(index: number): string;
28
89
  export type ReadResult = {
29
90
  readonly status: 'ok';
30
91
  readonly prefs: Preferences;
@@ -37,6 +98,14 @@ export type ReadResult = {
37
98
  export declare class PreferencesError extends Error {
38
99
  constructor(message: string);
39
100
  }
101
+ /**
102
+ * The member that actually runs.
103
+ *
104
+ * A helper rather than `prefs.providers[0]` at each call site: the chain is
105
+ * guaranteed non-empty by validation, and every reader repeating an index
106
+ * lookup plus a non-null assertion would be four places to get that wrong.
107
+ */
108
+ export declare function primaryProvider(prefs: Preferences): ProviderChoice;
40
109
  export declare function preferencesPath(home?: string): string;
41
110
  export declare function readPreferences(home?: string): ReadResult;
42
111
  export declare function writePreferences(prefs: Preferences, home?: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/preferences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAI/C,eAAO,MAAM,wBAAwB,EAAG,CAAU,CAAA;AAElD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAA;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAA;CAC3D;AAED,MAAM,MAAM,UAAU,GACnB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/D,qBAAa,gBAAiB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI3B;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAEhE;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAkB,GAAG,UAAU,CAwCpE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,GAAE,MAAkB,GAAG,IAAI,CAgBnF"}
1
+ {"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/preferences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAOH,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAIlE,eAAO,MAAM,wBAAwB,EAAG,CAAU,CAAA;AAElD;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAA;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAA;IAC7C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAA;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAA;CAC3D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,MAAM,MAAM,UAAU,GACnB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/D,qBAAa,gBAAiB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI3B;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,CAclE;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAEhE;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAkB,GAAG,UAAU,CAyDpE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,GAAE,MAAkB,GAAG,IAAI,CAmBnF"}