scoutline 0.1.0 → 0.6.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 (242) hide show
  1. package/README.md +394 -7
  2. package/bin/scoutline.js +36 -15
  3. package/dist/capabilities/diagnostics.d.ts +135 -0
  4. package/dist/capabilities/diagnostics.d.ts.map +1 -0
  5. package/dist/capabilities/diagnostics.js +139 -0
  6. package/dist/capabilities/diagnostics.js.map +1 -0
  7. package/dist/capabilities/quota.d.ts +99 -0
  8. package/dist/capabilities/quota.d.ts.map +1 -0
  9. package/dist/capabilities/quota.js +129 -0
  10. package/dist/capabilities/quota.js.map +1 -0
  11. package/dist/capabilities/reader.d.ts +227 -0
  12. package/dist/capabilities/reader.d.ts.map +1 -0
  13. package/dist/capabilities/reader.js +100 -0
  14. package/dist/capabilities/reader.js.map +1 -0
  15. package/dist/capabilities/repository.d.ts +221 -0
  16. package/dist/capabilities/repository.d.ts.map +1 -0
  17. package/dist/capabilities/repository.js +172 -0
  18. package/dist/capabilities/repository.js.map +1 -0
  19. package/dist/capabilities/search.d.ts +110 -0
  20. package/dist/capabilities/search.d.ts.map +1 -0
  21. package/dist/capabilities/search.js +21 -0
  22. package/dist/capabilities/search.js.map +1 -0
  23. package/dist/capabilities/vision.d.ts +156 -0
  24. package/dist/capabilities/vision.d.ts.map +1 -0
  25. package/dist/capabilities/vision.js +111 -0
  26. package/dist/capabilities/vision.js.map +1 -0
  27. package/dist/command-invocation.d.ts +58 -0
  28. package/dist/command-invocation.d.ts.map +1 -0
  29. package/dist/command-invocation.js +95 -0
  30. package/dist/command-invocation.js.map +1 -0
  31. package/dist/commands/cache.d.ts +106 -0
  32. package/dist/commands/cache.d.ts.map +1 -0
  33. package/dist/commands/cache.js +203 -0
  34. package/dist/commands/cache.js.map +1 -0
  35. package/dist/commands/code.d.ts +11 -4
  36. package/dist/commands/code.d.ts.map +1 -1
  37. package/dist/commands/code.js +16 -42
  38. package/dist/commands/code.js.map +1 -1
  39. package/dist/commands/doctor.d.ts +69 -3
  40. package/dist/commands/doctor.d.ts.map +1 -1
  41. package/dist/commands/doctor.js +179 -52
  42. package/dist/commands/doctor.js.map +1 -1
  43. package/dist/commands/quota.d.ts +45 -3
  44. package/dist/commands/quota.d.ts.map +1 -1
  45. package/dist/commands/quota.js +116 -60
  46. package/dist/commands/quota.js.map +1 -1
  47. package/dist/commands/read.d.ts +76 -2
  48. package/dist/commands/read.d.ts.map +1 -1
  49. package/dist/commands/read.js +260 -121
  50. package/dist/commands/read.js.map +1 -1
  51. package/dist/commands/repo.d.ts +55 -4
  52. package/dist/commands/repo.d.ts.map +1 -1
  53. package/dist/commands/repo.js +115 -172
  54. package/dist/commands/repo.js.map +1 -1
  55. package/dist/commands/repository-explorer.d.ts +147 -0
  56. package/dist/commands/repository-explorer.d.ts.map +1 -0
  57. package/dist/commands/repository-explorer.js +550 -0
  58. package/dist/commands/repository-explorer.js.map +1 -0
  59. package/dist/commands/search.d.ts +27 -2
  60. package/dist/commands/search.d.ts.map +1 -1
  61. package/dist/commands/search.js +95 -103
  62. package/dist/commands/search.js.map +1 -1
  63. package/dist/commands/tools.d.ts +9 -3
  64. package/dist/commands/tools.d.ts.map +1 -1
  65. package/dist/commands/tools.js +29 -59
  66. package/dist/commands/tools.js.map +1 -1
  67. package/dist/commands/vision.d.ts +35 -9
  68. package/dist/commands/vision.d.ts.map +1 -1
  69. package/dist/commands/vision.js +184 -131
  70. package/dist/commands/vision.js.map +1 -1
  71. package/dist/index.d.ts +62 -1
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +580 -223
  74. package/dist/index.js.map +1 -1
  75. package/dist/lib/cache.d.ts +178 -12
  76. package/dist/lib/cache.d.ts.map +1 -1
  77. package/dist/lib/cache.js +377 -39
  78. package/dist/lib/cache.js.map +1 -1
  79. package/dist/lib/code-mode.d.ts +13 -0
  80. package/dist/lib/code-mode.d.ts.map +1 -1
  81. package/dist/lib/code-mode.js +26 -6
  82. package/dist/lib/code-mode.js.map +1 -1
  83. package/dist/lib/config.d.ts.map +1 -1
  84. package/dist/lib/config.js +15 -18
  85. package/dist/lib/config.js.map +1 -1
  86. package/dist/lib/errors.d.ts +89 -11
  87. package/dist/lib/errors.d.ts.map +1 -1
  88. package/dist/lib/errors.js +168 -21
  89. package/dist/lib/errors.js.map +1 -1
  90. package/dist/lib/execution.d.ts +190 -0
  91. package/dist/lib/execution.d.ts.map +1 -0
  92. package/dist/lib/execution.js +383 -0
  93. package/dist/lib/execution.js.map +1 -0
  94. package/dist/lib/index.d.ts +10 -2
  95. package/dist/lib/index.d.ts.map +1 -1
  96. package/dist/lib/index.js +10 -2
  97. package/dist/lib/index.js.map +1 -1
  98. package/dist/lib/mcp-client.d.ts +75 -16
  99. package/dist/lib/mcp-client.d.ts.map +1 -1
  100. package/dist/lib/mcp-client.js +173 -108
  101. package/dist/lib/mcp-client.js.map +1 -1
  102. package/dist/lib/mcp-config.d.ts +17 -0
  103. package/dist/lib/mcp-config.d.ts.map +1 -1
  104. package/dist/lib/mcp-config.js +29 -0
  105. package/dist/lib/mcp-config.js.map +1 -1
  106. package/dist/lib/monitor-client.d.ts +17 -3
  107. package/dist/lib/monitor-client.d.ts.map +1 -1
  108. package/dist/lib/monitor-client.js +23 -69
  109. package/dist/lib/monitor-client.js.map +1 -1
  110. package/dist/lib/output.d.ts +53 -7
  111. package/dist/lib/output.d.ts.map +1 -1
  112. package/dist/lib/output.js +126 -39
  113. package/dist/lib/output.js.map +1 -1
  114. package/dist/lib/redact.d.ts +62 -3
  115. package/dist/lib/redact.d.ts.map +1 -1
  116. package/dist/lib/redact.js +165 -31
  117. package/dist/lib/redact.js.map +1 -1
  118. package/dist/lib/tool-cache.d.ts +86 -0
  119. package/dist/lib/tool-cache.d.ts.map +1 -0
  120. package/dist/lib/tool-cache.js +123 -0
  121. package/dist/lib/tool-cache.js.map +1 -0
  122. package/dist/lib/tty.d.ts +7 -20
  123. package/dist/lib/tty.d.ts.map +1 -1
  124. package/dist/lib/tty.js +51 -30
  125. package/dist/lib/tty.js.map +1 -1
  126. package/dist/node-command-invocation-adapter.d.ts +28 -0
  127. package/dist/node-command-invocation-adapter.d.ts.map +1 -0
  128. package/dist/node-command-invocation-adapter.js +88 -0
  129. package/dist/node-command-invocation-adapter.js.map +1 -0
  130. package/dist/providers/minimax/adapter.d.ts +49 -0
  131. package/dist/providers/minimax/adapter.d.ts.map +1 -0
  132. package/dist/providers/minimax/adapter.js +450 -0
  133. package/dist/providers/minimax/adapter.js.map +1 -0
  134. package/dist/providers/minimax/coding-plan-client.d.ts +60 -0
  135. package/dist/providers/minimax/coding-plan-client.d.ts.map +1 -0
  136. package/dist/providers/minimax/coding-plan-client.js +204 -0
  137. package/dist/providers/minimax/coding-plan-client.js.map +1 -0
  138. package/dist/providers/minimax/config.d.ts +32 -0
  139. package/dist/providers/minimax/config.d.ts.map +1 -0
  140. package/dist/providers/minimax/config.js +84 -0
  141. package/dist/providers/minimax/config.js.map +1 -0
  142. package/dist/providers/minimax/media.d.ts +88 -0
  143. package/dist/providers/minimax/media.d.ts.map +1 -0
  144. package/dist/providers/minimax/media.js +232 -0
  145. package/dist/providers/minimax/media.js.map +1 -0
  146. package/dist/providers/minimax/quota-client.d.ts +44 -0
  147. package/dist/providers/minimax/quota-client.d.ts.map +1 -0
  148. package/dist/providers/minimax/quota-client.js +83 -0
  149. package/dist/providers/minimax/quota-client.js.map +1 -0
  150. package/dist/providers/minimax/quota.d.ts +48 -0
  151. package/dist/providers/minimax/quota.d.ts.map +1 -0
  152. package/dist/providers/minimax/quota.js +120 -0
  153. package/dist/providers/minimax/quota.js.map +1 -0
  154. package/dist/providers/minimax/sdk-client.d.ts +29 -0
  155. package/dist/providers/minimax/sdk-client.d.ts.map +1 -0
  156. package/dist/providers/minimax/sdk-client.js +50 -0
  157. package/dist/providers/minimax/sdk-client.js.map +1 -0
  158. package/dist/providers/minimax/vision-attestations.d.ts +52 -0
  159. package/dist/providers/minimax/vision-attestations.d.ts.map +1 -0
  160. package/dist/providers/minimax/vision-attestations.js +79 -0
  161. package/dist/providers/minimax/vision-attestations.js.map +1 -0
  162. package/dist/providers/minimax/vision-conformance.d.ts +186 -0
  163. package/dist/providers/minimax/vision-conformance.d.ts.map +1 -0
  164. package/dist/providers/minimax/vision-conformance.js +371 -0
  165. package/dist/providers/minimax/vision-conformance.js.map +1 -0
  166. package/dist/providers/minimax/vision-mappings/chart.d.ts +35 -0
  167. package/dist/providers/minimax/vision-mappings/chart.d.ts.map +1 -0
  168. package/dist/providers/minimax/vision-mappings/chart.js +55 -0
  169. package/dist/providers/minimax/vision-mappings/chart.js.map +1 -0
  170. package/dist/providers/minimax/vision-mappings/common.d.ts +60 -0
  171. package/dist/providers/minimax/vision-mappings/common.d.ts.map +1 -0
  172. package/dist/providers/minimax/vision-mappings/common.js +75 -0
  173. package/dist/providers/minimax/vision-mappings/common.js.map +1 -0
  174. package/dist/providers/minimax/vision-mappings/diagnose-error.d.ts +35 -0
  175. package/dist/providers/minimax/vision-mappings/diagnose-error.d.ts.map +1 -0
  176. package/dist/providers/minimax/vision-mappings/diagnose-error.js +55 -0
  177. package/dist/providers/minimax/vision-mappings/diagnose-error.js.map +1 -0
  178. package/dist/providers/minimax/vision-mappings/diagram.d.ts +35 -0
  179. package/dist/providers/minimax/vision-mappings/diagram.d.ts.map +1 -0
  180. package/dist/providers/minimax/vision-mappings/diagram.js +55 -0
  181. package/dist/providers/minimax/vision-mappings/diagram.js.map +1 -0
  182. package/dist/providers/minimax/vision-mappings/extract-text.d.ts +35 -0
  183. package/dist/providers/minimax/vision-mappings/extract-text.d.ts.map +1 -0
  184. package/dist/providers/minimax/vision-mappings/extract-text.js +55 -0
  185. package/dist/providers/minimax/vision-mappings/extract-text.js.map +1 -0
  186. package/dist/providers/minimax/vision-mappings/ui-artifact.d.ts +35 -0
  187. package/dist/providers/minimax/vision-mappings/ui-artifact.d.ts.map +1 -0
  188. package/dist/providers/minimax/vision-mappings/ui-artifact.js +69 -0
  189. package/dist/providers/minimax/vision-mappings/ui-artifact.js.map +1 -0
  190. package/dist/providers/minimax/vision-mappings.generated.d.ts +29 -0
  191. package/dist/providers/minimax/vision-mappings.generated.d.ts.map +1 -0
  192. package/dist/providers/minimax/vision-mappings.generated.js +29 -0
  193. package/dist/providers/minimax/vision-mappings.generated.js.map +1 -0
  194. package/dist/providers/minimax/vision-revisions.d.ts +29 -0
  195. package/dist/providers/minimax/vision-revisions.d.ts.map +1 -0
  196. package/dist/providers/minimax/vision-revisions.js +34 -0
  197. package/dist/providers/minimax/vision-revisions.js.map +1 -0
  198. package/dist/providers/registry.d.ts +36 -0
  199. package/dist/providers/registry.d.ts.map +1 -0
  200. package/dist/providers/registry.js +45 -0
  201. package/dist/providers/registry.js.map +1 -0
  202. package/dist/providers/selection.d.ts +44 -0
  203. package/dist/providers/selection.d.ts.map +1 -0
  204. package/dist/providers/selection.js +85 -0
  205. package/dist/providers/selection.js.map +1 -0
  206. package/dist/providers/types.d.ts +281 -0
  207. package/dist/providers/types.d.ts.map +1 -0
  208. package/dist/providers/types.js +127 -0
  209. package/dist/providers/types.js.map +1 -0
  210. package/dist/providers/zai/adapter.d.ts +35 -0
  211. package/dist/providers/zai/adapter.d.ts.map +1 -0
  212. package/dist/providers/zai/adapter.js +685 -0
  213. package/dist/providers/zai/adapter.js.map +1 -0
  214. package/dist/providers/zai/credentials.d.ts +38 -0
  215. package/dist/providers/zai/credentials.d.ts.map +1 -0
  216. package/dist/providers/zai/credentials.js +60 -0
  217. package/dist/providers/zai/credentials.js.map +1 -0
  218. package/dist/providers/zai/encoded-error.d.ts +90 -0
  219. package/dist/providers/zai/encoded-error.d.ts.map +1 -0
  220. package/dist/providers/zai/encoded-error.js +169 -0
  221. package/dist/providers/zai/encoded-error.js.map +1 -0
  222. package/dist/providers/zai/media.d.ts +38 -0
  223. package/dist/providers/zai/media.d.ts.map +1 -0
  224. package/dist/providers/zai/media.js +107 -0
  225. package/dist/providers/zai/media.js.map +1 -0
  226. package/dist/providers/zai/monitor-client.d.ts +53 -0
  227. package/dist/providers/zai/monitor-client.d.ts.map +1 -0
  228. package/dist/providers/zai/monitor-client.js +117 -0
  229. package/dist/providers/zai/monitor-client.js.map +1 -0
  230. package/dist/providers/zai/quota.d.ts +47 -0
  231. package/dist/providers/zai/quota.d.ts.map +1 -0
  232. package/dist/providers/zai/quota.js +127 -0
  233. package/dist/providers/zai/quota.js.map +1 -0
  234. package/dist/providers/zai/reader.d.ts +82 -0
  235. package/dist/providers/zai/reader.d.ts.map +1 -0
  236. package/dist/providers/zai/reader.js +490 -0
  237. package/dist/providers/zai/reader.js.map +1 -0
  238. package/dist/providers/zai/repository.d.ts +76 -0
  239. package/dist/providers/zai/repository.d.ts.map +1 -0
  240. package/dist/providers/zai/repository.js +715 -0
  241. package/dist/providers/zai/repository.js.map +1 -0
  242. package/package.json +11 -6
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Diagnostics Capability Contract (DESIGN.md §14, P4-04, P6-06).
3
+ *
4
+ * Defines the schema-version-1 diagnostics report every `doctor`
5
+ * invocation returns, plus the capability contract each Provider
6
+ * Adapter implements so its connectivity can be probed without a
7
+ * generative request.
8
+ *
9
+ * The report is built by the doctor command from descriptor-derived
10
+ * inventory plus the success/failure of each configured Provider
11
+ * probe. Each Adapter performs exactly ONE connectivity attempt;
12
+ * shared execution owns the retry policy.
13
+ *
14
+ * Boundary rules (ARCHITECTURE.md §2):
15
+ * - Imports Provider identity and metadata types (`ProviderCapability`,
16
+ * `ProviderDescriptor`, `ProviderId`) and shared errors. P6-06 keeps
17
+ * the inventory descriptor-derived; no concrete Adapter, no
18
+ * Provider transport, no production registry import lives here.
19
+ * - Imports no Provider transport, no Provider Adapter, no Vision
20
+ * operation→capability mapping, no MiniMax specialized-vision
21
+ * conformance registry, no command presentation. The previous
22
+ * hand-maintained inventory required those imports; the
23
+ * descriptor-derived inventory does not.
24
+ *
25
+ * Inventory derivation (P6-06):
26
+ * - `sharedCapabilities` is the intersection across every descriptor
27
+ * passed to `buildDiagnosticsReport`, preserving deterministic
28
+ * canonical order from the FIRST descriptor.
29
+ * - `zaiOnlyCapabilities` is the Z.AI descriptor's capabilities
30
+ * minus the union of every OTHER built-in descriptor's
31
+ * capabilities, preserving Z.AI descriptor order. Values are
32
+ * descriptor capability IDs only — no hand-maintained aliases.
33
+ * - `repository-exploration` is excluded from shared while any
34
+ * built-in lacks it, and included in Z.AI-only the moment Z.AI
35
+ * advertises it and another built-in does not.
36
+ */
37
+ import { ScoutlineError } from "../lib/errors.js";
38
+ // ---------------------------------------------------------------------------
39
+ // Descriptor-derived inventory (P6-06).
40
+ //
41
+ // Pure calculations over the exact descriptor list passed to
42
+ // `buildDiagnosticsReport`. No descriptor.create(), no transport, no
43
+ // production registry import. Empty/single/missing-ZAI lists are
44
+ // handled deterministically; the algorithms never rely on array
45
+ // indexing accidents.
46
+ // ---------------------------------------------------------------------------
47
+ /**
48
+ * Derive the shared Capabilities inventory: the intersection of every
49
+ * descriptor's `capabilities()` set, preserving deterministic
50
+ * canonical order from the FIRST descriptor in the list.
51
+ *
52
+ * Edge cases:
53
+ * - Empty descriptor list: returns an empty array.
54
+ * - Single descriptor: returns that descriptor's capabilities in
55
+ * their declared order (the intersection of one set is itself).
56
+ * - Two or more: keeps a capability from the first descriptor iff
57
+ * every other descriptor also advertises it.
58
+ *
59
+ * The returned array is frozen so callers cannot mutate the cached
60
+ * derivation in place.
61
+ */
62
+ export function deriveSharedCapabilities(descriptors) {
63
+ if (descriptors.length === 0)
64
+ return Object.freeze([]);
65
+ const [first, ...rest] = descriptors;
66
+ if (rest.length === 0) {
67
+ return Object.freeze([...first.capabilities()]);
68
+ }
69
+ const otherSets = rest.map((d) => d.capabilities());
70
+ const out = [];
71
+ for (const cap of first.capabilities()) {
72
+ if (otherSets.every((set) => set.has(cap))) {
73
+ out.push(cap);
74
+ }
75
+ }
76
+ return Object.freeze(out);
77
+ }
78
+ /**
79
+ * Derive the Z.AI-only Capabilities inventory: capabilities advertised
80
+ * by the Z.AI descriptor minus the union of capabilities advertised by
81
+ * every OTHER descriptor in the list. Preserves Z.AI descriptor order.
82
+ *
83
+ * Edge cases:
84
+ * - Empty descriptor list: returns an empty array.
85
+ * - Z.AI absent from the list: returns an empty array.
86
+ * - Z.AI present as the only descriptor: returns its capabilities
87
+ * verbatim (the "minus nothing" case).
88
+ * - Z.AI with other descriptors: each capability in Z.AI descriptor
89
+ * order is kept iff no other descriptor advertises it.
90
+ *
91
+ * The returned values are descriptor capability IDs only. No
92
+ * hand-maintained aliases, no parallel base-release list, no
93
+ * invented names. `repository-exploration` lands here naturally the
94
+ * moment Z.AI advertises it and another built-in does not.
95
+ */
96
+ export function deriveZaiOnlyCapabilities(descriptors) {
97
+ const zai = descriptors.find((d) => d.id === "zai");
98
+ if (!zai)
99
+ return Object.freeze([]);
100
+ const others = descriptors.filter((d) => d.id !== "zai");
101
+ if (others.length === 0) {
102
+ return Object.freeze([...zai.capabilities()]);
103
+ }
104
+ const union = new Set();
105
+ for (const descriptor of others) {
106
+ for (const cap of descriptor.capabilities()) {
107
+ union.add(cap);
108
+ }
109
+ }
110
+ const out = [];
111
+ for (const cap of zai.capabilities()) {
112
+ if (!union.has(cap)) {
113
+ out.push(cap);
114
+ }
115
+ }
116
+ return Object.freeze(out);
117
+ }
118
+ // ---------------------------------------------------------------------------
119
+ // Failure normalization
120
+ // ---------------------------------------------------------------------------
121
+ /**
122
+ * Map a thrown error into a normalized diagnostic error entry. The
123
+ * caller is responsible for recursive redaction before the entry
124
+ * crosses an outward boundary (the doctor command does this in
125
+ * {@link buildDiagnosticsReport}).
126
+ */
127
+ export function diagnosticErrorFromError(error) {
128
+ const code = error instanceof ScoutlineError ? error.code : "UNKNOWN_ERROR";
129
+ const message = error instanceof Error ? error.message : String(error);
130
+ const result = {
131
+ code,
132
+ message,
133
+ };
134
+ if (error instanceof ScoutlineError && error.help) {
135
+ result.help = error.help;
136
+ }
137
+ return result;
138
+ }
139
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/capabilities/diagnostics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Quota Capability Contract (DESIGN.md §13, ADR-0001).
3
+ *
4
+ * Defines the normalized Provider-quota Interface shared by every
5
+ * Provider that reports plan usage. Each Adapter maps its Provider
6
+ * response shape into named quota categories with current and optional
7
+ * weekly windows, optional counts, a remaining percentage, and a reset
8
+ * time so callers do not need Provider-specific knowledge.
9
+ *
10
+ * Normalization rules (DESIGN.md §13):
11
+ * - Percentages are REMAINING percentages clamped to 0..100.
12
+ * - A valid explicit remaining percentage wins; otherwise derive
13
+ * `(remaining / limit) * 100` from finite nonnegative counts where
14
+ * used is not greater than limit.
15
+ * - Invalid optional counts are omitted together (not set to zero).
16
+ * - A category that has neither a valid percentage nor valid counts
17
+ * is rejected with `QUOTA_ERROR`.
18
+ * - Nonempty names, finite values, and ISO dates are mandatory.
19
+ *
20
+ * This module imports only Provider identity types and shared errors;
21
+ * it imports no Provider transport and no Provider Adapter.
22
+ */
23
+ import type { ProviderId } from "../providers/types.js";
24
+ import { type ScoutlineErrorCode } from "../lib/errors.js";
25
+ export interface QuotaWindow {
26
+ durationSeconds?: number;
27
+ used?: number;
28
+ limit?: number;
29
+ remaining?: number;
30
+ remainingPercent: number;
31
+ resetsAt?: string;
32
+ }
33
+ export interface QuotaCategory {
34
+ name: string;
35
+ unit: "requests" | "tokens";
36
+ current: QuotaWindow;
37
+ weekly?: QuotaWindow;
38
+ }
39
+ export interface ProviderQuotaSuccess {
40
+ provider: ProviderId;
41
+ status: "ok";
42
+ plan?: string;
43
+ categories: QuotaCategory[];
44
+ }
45
+ export interface ProviderQuotaFailure {
46
+ provider: ProviderId;
47
+ status: "error";
48
+ error: {
49
+ code: ScoutlineErrorCode;
50
+ message: string;
51
+ help?: string;
52
+ };
53
+ }
54
+ export interface QuotaDashboard {
55
+ schemaVersion: 1;
56
+ effectiveProvider: ProviderId;
57
+ providers: Array<ProviderQuotaSuccess | ProviderQuotaFailure>;
58
+ }
59
+ export interface QuotaCapability {
60
+ invoke(): Promise<ProviderQuotaSuccess>;
61
+ }
62
+ /**
63
+ * Inputs to {@link buildQuotaWindow}. Every field is optional except
64
+ * that at least one of `explicitRemainingPercent` or a valid count set
65
+ * (`used` + `limit`) must be present, otherwise the window is
66
+ * unrecoverable and `QUOTA_ERROR` is thrown.
67
+ */
68
+ export interface QuotaWindowInputs {
69
+ durationSeconds?: number;
70
+ used?: number;
71
+ limit?: number;
72
+ resetsAtEpochMs?: number;
73
+ /**
74
+ * A Provider-supplied REMAINING percentage (already in remaining
75
+ * terms, not used terms). A finite value wins over count-derived
76
+ * derivation and is then clamped to 0..100.
77
+ */
78
+ explicitRemainingPercent?: number;
79
+ }
80
+ /**
81
+ * Build a normalized {@link QuotaWindow} from Provider inputs.
82
+ *
83
+ * Resolution order for `remainingPercent`:
84
+ * 1. A finite explicit remaining percentage wins (then clamped).
85
+ * 2. Otherwise derive from valid counts.
86
+ * 3. Otherwise throw `QUOTA_ERROR` — the category is unrecoverable.
87
+ *
88
+ * Invalid optional counts are omitted together; valid counts populate
89
+ * `used`, `limit`, and a derived `remaining`. `durationSeconds` and
90
+ * `resetsAt` are included only when finite/ISO-valid.
91
+ */
92
+ export declare function buildQuotaWindow(inputs: QuotaWindowInputs): QuotaWindow;
93
+ /**
94
+ * Map a thrown error into a normalized {@link ProviderQuotaFailure}. The
95
+ * caller is responsible for recursive redaction before the failure
96
+ * crosses an outward boundary (all-provider quota does this in P4-03).
97
+ */
98
+ export declare function quotaFailureFromError(provider: ProviderId, error: unknown): ProviderQuotaFailure;
99
+ //# sourceMappingURL=quota.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota.d.ts","sourceRoot":"","sources":["../../src/capabilities/quota.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAkB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAM3E,MAAM,WAAW,WAAW;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC5B,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,IAAI,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE;QAAE,IAAI,EAAE,kBAAkB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,CAAC,CAAC;IACjB,iBAAiB,EAAE,UAAU,CAAC;IAC9B,SAAS,EAAE,KAAK,CAAC,oBAAoB,GAAG,oBAAoB,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACzC;AAMD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAkDD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAoCvE;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAahG"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Quota Capability Contract (DESIGN.md §13, ADR-0001).
3
+ *
4
+ * Defines the normalized Provider-quota Interface shared by every
5
+ * Provider that reports plan usage. Each Adapter maps its Provider
6
+ * response shape into named quota categories with current and optional
7
+ * weekly windows, optional counts, a remaining percentage, and a reset
8
+ * time so callers do not need Provider-specific knowledge.
9
+ *
10
+ * Normalization rules (DESIGN.md §13):
11
+ * - Percentages are REMAINING percentages clamped to 0..100.
12
+ * - A valid explicit remaining percentage wins; otherwise derive
13
+ * `(remaining / limit) * 100` from finite nonnegative counts where
14
+ * used is not greater than limit.
15
+ * - Invalid optional counts are omitted together (not set to zero).
16
+ * - A category that has neither a valid percentage nor valid counts
17
+ * is rejected with `QUOTA_ERROR`.
18
+ * - Nonempty names, finite values, and ISO dates are mandatory.
19
+ *
20
+ * This module imports only Provider identity types and shared errors;
21
+ * it imports no Provider transport and no Provider Adapter.
22
+ */
23
+ import { ScoutlineError } from "../lib/errors.js";
24
+ function isFiniteNonnegative(value) {
25
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
26
+ }
27
+ function isFinitePositive(value) {
28
+ return typeof value === "number" && Number.isFinite(value) && value > 0;
29
+ }
30
+ function clampPercent(value) {
31
+ if (value < 0)
32
+ return 0;
33
+ if (value > 100)
34
+ return 100;
35
+ return value;
36
+ }
37
+ /**
38
+ * Validate a count set: both `used` and `limit` must be finite,
39
+ * nonnegative, with `used` not greater than `limit`. Returns the pair
40
+ * or `null` so an invalid set can be omitted together.
41
+ */
42
+ function validCountSet(used, limit) {
43
+ if (!isFiniteNonnegative(used) || !isFiniteNonnegative(limit))
44
+ return null;
45
+ if (used > limit)
46
+ return null;
47
+ return { used: used, limit: limit };
48
+ }
49
+ /**
50
+ * Derive a remaining percentage from finite nonnegative counts where
51
+ * used is not greater than limit and limit is positive. Returns `null`
52
+ * when the counts cannot yield a percentage.
53
+ */
54
+ function derivePercentFromCounts(used, limit) {
55
+ const counts = validCountSet(used, limit);
56
+ if (counts === null)
57
+ return null;
58
+ if (counts.limit <= 0)
59
+ return null;
60
+ return ((counts.limit - counts.used) / counts.limit) * 100;
61
+ }
62
+ function epochMsToIso(epochMs) {
63
+ if (!isFinitePositive(epochMs))
64
+ return undefined;
65
+ return new Date(epochMs).toISOString();
66
+ }
67
+ /**
68
+ * Build a normalized {@link QuotaWindow} from Provider inputs.
69
+ *
70
+ * Resolution order for `remainingPercent`:
71
+ * 1. A finite explicit remaining percentage wins (then clamped).
72
+ * 2. Otherwise derive from valid counts.
73
+ * 3. Otherwise throw `QUOTA_ERROR` — the category is unrecoverable.
74
+ *
75
+ * Invalid optional counts are omitted together; valid counts populate
76
+ * `used`, `limit`, and a derived `remaining`. `durationSeconds` and
77
+ * `resetsAt` are included only when finite/ISO-valid.
78
+ */
79
+ export function buildQuotaWindow(inputs) {
80
+ let remainingPercent;
81
+ if (Number.isFinite(inputs.explicitRemainingPercent)) {
82
+ remainingPercent = inputs.explicitRemainingPercent;
83
+ }
84
+ else {
85
+ const derived = derivePercentFromCounts(inputs.used, inputs.limit);
86
+ if (derived !== null)
87
+ remainingPercent = derived;
88
+ }
89
+ if (remainingPercent === undefined) {
90
+ throw new ScoutlineError("quota category has neither a valid remaining percentage nor valid counts", "QUOTA_ERROR", { exitCode: 1 });
91
+ }
92
+ const window = { remainingPercent: clampPercent(remainingPercent) };
93
+ const counts = validCountSet(inputs.used, inputs.limit);
94
+ if (counts !== null) {
95
+ window.used = counts.used;
96
+ window.limit = counts.limit;
97
+ window.remaining = counts.limit - counts.used;
98
+ }
99
+ if (isFinitePositive(inputs.durationSeconds)) {
100
+ window.durationSeconds = inputs.durationSeconds;
101
+ }
102
+ const iso = epochMsToIso(inputs.resetsAtEpochMs);
103
+ if (iso !== undefined) {
104
+ window.resetsAt = iso;
105
+ }
106
+ return window;
107
+ }
108
+ // ---------------------------------------------------------------------------
109
+ // Failure normalization
110
+ // ---------------------------------------------------------------------------
111
+ /**
112
+ * Map a thrown error into a normalized {@link ProviderQuotaFailure}. The
113
+ * caller is responsible for recursive redaction before the failure
114
+ * crosses an outward boundary (all-provider quota does this in P4-03).
115
+ */
116
+ export function quotaFailureFromError(provider, error) {
117
+ const code = error instanceof ScoutlineError ? error.code : "UNKNOWN_ERROR";
118
+ const message = error instanceof Error ? error.message : String(error);
119
+ const failure = {
120
+ provider,
121
+ status: "error",
122
+ error: { code, message },
123
+ };
124
+ if (error instanceof ScoutlineError && error.help) {
125
+ failure.error.help = error.help;
126
+ }
127
+ return failure;
128
+ }
129
+ //# sourceMappingURL=quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota.js","sourceRoot":"","sources":["../../src/capabilities/quota.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Provider-neutral Reader Capability Contract (core-flows D1, D2;
3
+ * tech-plan D1, D2).
4
+ *
5
+ * This module declares the single Reader operation (`reader-fetch`), its
6
+ * provider-neutral request, identity, cache, and result shapes, the total
7
+ * normalized cache decoder, and the `ReaderRawResponse` type capturing
8
+ * what the Z.AI WebReader MCP actually returns at runtime.
9
+ *
10
+ * It imports NO concrete Provider, transport, or Adapter. It does no URL
11
+ * rewriting, raw response parsing, Provider field mapping, Provider
12
+ * selection, retries, or presentation.
13
+ *
14
+ * Scope of this file:
15
+ * - request, operation, cache-identity, and result type contracts;
16
+ * - the discriminated `ReaderOperationKind` union;
17
+ * - a total decoder for the cacheable normalized result
18
+ * (`decodeReaderFetchResult`);
19
+ * - the `ReaderRawResponse` type consumed by Ticket 02's `webRead`
20
+ * signature fix.
21
+ *
22
+ * Ticket 01 introduces ONLY this contract and the decoder. Ticket 02
23
+ * fixes `webRead` to return `ReaderRawResponse`. Ticket 03 supplies the
24
+ * Z.AI Reader Adapter. Ticket 04 cuts the handler over. Nothing in this
25
+ * file is allowed to widen that boundary.
26
+ *
27
+ * Evidence base: [`artifacts/reader-webreader-characterization/`](../../../../.traycer/epics/4f065460-3416-4832-95a6-7ac5576fcfbc/artifacts/reader-webreader-characterization/index.md).
28
+ */
29
+ import type { ProviderId } from "../providers/types.js";
30
+ /**
31
+ * The single Reader Capability operation. Cache identity partitions by
32
+ * the composite `${capability}-${operation}` literal; the v2 partitioned
33
+ * key shape is
34
+ * `v2.reader-reader-fetch.<provider>.<credential-hash>.<request-hash>.json`.
35
+ *
36
+ * `--extract` and `--max-chars` are handler-level projections and do
37
+ * NOT participate in the cache identity (tech-plan D1, D2).
38
+ */
39
+ export type ReaderOperationKind = "reader-fetch";
40
+ /**
41
+ * Provider-neutral Reader fetch request. `url` MUST be supplied
42
+ * explicitly (the handler rejects non-`http(s)` values at parse time
43
+ * with `VALIDATION_ERROR` before this request reaches the Adapter).
44
+ *
45
+ * Every field except `url` participates in the v0.2 legacy cache key
46
+ * (`buildLegacyReaderCacheKey`) and in the v2 partitioned cache identity
47
+ * (`buildProviderCacheKey`). `--extract`, `--max-chars`, `--full-envelope`,
48
+ * `--no-cache`, and output mode NEVER appear here — they are projections
49
+ * applied after the cached normalized result.
50
+ *
51
+ * Field name parity with the v0.2 `webRead` request shape is intentional;
52
+ * the Adapter maps each field to the Z.AI WebReader MCP argument of the
53
+ * same semantics. The field order in the v0.2 insertion-order key is
54
+ * locked by the legacy helper, not by this interface.
55
+ */
56
+ export interface ReaderFetchRequest {
57
+ readonly url: string;
58
+ readonly format?: "markdown" | "text";
59
+ readonly retainImages?: boolean;
60
+ readonly withLinksSummary?: boolean;
61
+ readonly noGfm?: boolean;
62
+ readonly keepImgDataUrl?: boolean;
63
+ readonly withImagesSummary?: boolean;
64
+ readonly timeout?: number;
65
+ }
66
+ /**
67
+ * Normalized Reader fetch result. `schemaVersion: 1` is the breaking
68
+ * migration shape (core-flows D1 — `data`-mode returns the envelope,
69
+ * not a raw string).
70
+ *
71
+ * `truncated` and `originalContentLength` are NOT part of this contract.
72
+ * They are handler-level projections applied by `commands/read.ts` after
73
+ * the cached normalized result is produced (tech-plan D5). The cache
74
+ * stores the full content; truncation state is recomputed on every read.
75
+ *
76
+ * `title` is `string | null`. Every observed Z.AI WebReader response
77
+ * carries a non-empty string title (see characterization artifact), but
78
+ * the contract keeps the nullable arm for forward-compat and for
79
+ * Adapter-side coercion of empty / whitespace-only titles.
80
+ *
81
+ * `metadata` and `external` are typed `unknown` defensively. The
82
+ * characterization probe observed both as flat object maps, but the
83
+ * contract does not promote or restructure them — they pass through
84
+ * verbatim from the Provider.
85
+ */
86
+ export interface ReaderFetchResult {
87
+ readonly schemaVersion: 1;
88
+ /** Exactly what the caller passed to the operation. */
89
+ readonly url: string;
90
+ /**
91
+ * The URL the operation actually fetched. Differs from `url` only when
92
+ * a Provider-side rewrite occurred (e.g. `gist.github.com/<id>` →
93
+ * `gist.github.com/<id>/raw`).
94
+ */
95
+ readonly finalUrl: string;
96
+ /** Page title if the Provider returned one; `null` if absent or blank. */
97
+ readonly title: string | null;
98
+ /** Page content as markdown or plain text per `format`. */
99
+ readonly content: string;
100
+ /** Mirrors the request `format`; defaults to `"markdown"`. */
101
+ readonly contentFormat: "markdown" | "text";
102
+ /** Optional Provider-derived metadata blob; preserved verbatim. */
103
+ readonly metadata?: unknown;
104
+ /** Optional Provider-derived external-resource blob; preserved verbatim. */
105
+ readonly external?: unknown;
106
+ }
107
+ /**
108
+ * Object shape of a successful Z.AI WebReader MCP response. Field names
109
+ * mirror the wire shape observed in the characterization probe. Every
110
+ * field is optional at the wire layer — the Capability decoder enforces
111
+ * the stronger invariants (`title`, `url`, `content` must be non-empty
112
+ * strings) before promoting any value into a `ReaderFetchResult`.
113
+ *
114
+ * `description` is declared here so the Adapter can read it without
115
+ * crashing on rich pages (the probe confirmed `description` appears
116
+ * both at the top level and inside `metadata` for rich pages). The v1
117
+ * envelope does NOT surface it; it is dropped during normalization.
118
+ */
119
+ export interface ReaderRawObjectResponse {
120
+ readonly title?: string;
121
+ readonly description?: string;
122
+ readonly url?: string;
123
+ readonly content?: string;
124
+ readonly metadata?: unknown;
125
+ readonly external?: unknown;
126
+ }
127
+ /**
128
+ * The complete raw shape returned by `scoutline.zai.reader.webReader` at
129
+ * runtime. Either a structured object (the common case) or a bare
130
+ * `string` carrying an MCP-level error envelope (the characterization
131
+ * probe captured the exact shape: `"MCP error -500: ..."`).
132
+ *
133
+ * Ticket 02 widens the existing `webRead` method's TypeScript signature from
134
+ * the inaccurate `Promise<string>` to `Promise<ReaderRawResponse>` so
135
+ * raw-tool callers (`scoutline.zai.reader.*`) and the future Reader
136
+ * Adapter both see an honest path.
137
+ *
138
+ * The Capability decoder (`decodeReaderFetchResult`) only trusts
139
+ * object-shape values that satisfy the required field set. A raw
140
+ * `string` is malformed at the Capability layer — it represents a
141
+ * transport-level error that the Adapter must convert into a normalized
142
+ * `API_ERROR` 502 per the failure-handling table, not a fetch result.
143
+ */
144
+ export type ReaderRawResponse = ReaderRawObjectResponse | string;
145
+ /**
146
+ * Provider-owned legacy cache candidate. Old Z.AI v0.2 read cache entries
147
+ * encode the raw WebReader response under the public dotted tool name
148
+ * (`scoutline.zai.reader.webReader`). The Adapter supplies the decoder
149
+ * so shared cache code never inspects Provider response shapes. An
150
+ * invalid decode is a cache miss.
151
+ */
152
+ export interface LegacyReaderCacheCandidate<Result> {
153
+ readonly key: string;
154
+ decode(value: unknown): Result | null;
155
+ }
156
+ /**
157
+ * Identity used to read and write a Provider-partitioned Reader cache
158
+ * entry. `credentialFingerprint` is the full lowercase SHA-256 hex
159
+ * digest of the resolved credential and is NEVER re-hashed by cache
160
+ * code. `request` is the normalized Capability request.
161
+ */
162
+ export interface ReaderCacheIdentity<Request, Result> {
163
+ readonly provider: ProviderId;
164
+ readonly capability: "reader";
165
+ readonly operation: ReaderOperationKind;
166
+ readonly credentialFingerprint: string;
167
+ readonly request: Readonly<Request>;
168
+ readonly legacyCandidates: readonly LegacyReaderCacheCandidate<Result>[];
169
+ }
170
+ /**
171
+ * Generic Reader operation descriptor. The Adapter supplies one of these
172
+ * for the `reader-fetch` operation it supports. The Adapter owns
173
+ * Provider field mapping, credentials, transport lifecycle, and error
174
+ * normalization. Commands and shared execution call only these four
175
+ * methods.
176
+ *
177
+ * Same shape as P6-02's `RepositoryOperation` — the surface is
178
+ * unchanged; only the operation count differs (Reader has one).
179
+ */
180
+ export interface ReaderOperation<Request, Result> {
181
+ readonly kind: ReaderOperationKind;
182
+ /**
183
+ * Validate the request before any Provider access. Throws
184
+ * `ValidationError` for missing required fields and
185
+ * `UnsupportedOptionError` for Provider-specific options the Adapter
186
+ * does not accept. Validation MUST occur before credential resolution
187
+ * or transport construction.
188
+ */
189
+ validate(request: Request): void;
190
+ /**
191
+ * Build the cache identity for a request. Called only after
192
+ * `validate` succeeds. The Adapter resolves its credential once and
193
+ * returns full fingerprint, canonical request, and zero or more
194
+ * legacy candidates. Candidate construction MUST NOT read ambient
195
+ * environment.
196
+ */
197
+ cacheIdentity(request: Request): ReaderCacheIdentity<Request, Result>;
198
+ /**
199
+ * Total decoder for cached normalized entries. Accepts an `unknown`
200
+ * value, validates shape, and returns the typed result or `null`.
201
+ * NEVER throws, NEVER trusts a generic cast.
202
+ */
203
+ decodeCached(value: unknown): Result | null;
204
+ /**
205
+ * Invoke the Provider and return the normalized result. The Adapter
206
+ * closes its transport and never retries inside this method; shared
207
+ * execution owns retry policy.
208
+ */
209
+ invoke(request: Request): Promise<Result>;
210
+ }
211
+ /**
212
+ * Reader Capability contract. Every Adapter that supports reader
213
+ * fetching implements this interface and exposes it as
214
+ * `adapter.reader` (Ticket 03 onwards).
215
+ */
216
+ export interface ReaderCapability {
217
+ readonly fetch: ReaderOperation<ReaderFetchRequest, ReaderFetchResult>;
218
+ }
219
+ /**
220
+ * Decode a Reader fetch result from the cache. Returns the canonical
221
+ * `ReaderFetchResult` on success, `null` for any malformed value.
222
+ *
223
+ * `title: null` is a valid decoded value (the Adapter coerces missing
224
+ * or blank titles to null before writing; the decoder round-trips it).
225
+ */
226
+ export declare function decodeReaderFetchResult(value: unknown): ReaderFetchResult | null;
227
+ //# sourceMappingURL=reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../src/capabilities/reader.ts"],"names":[],"mappings":"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"}