copilot-usage-studio 0.2.0 → 0.2.2

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 (38) hide show
  1. package/CHANGELOG.md +30 -2
  2. package/README.md +46 -13
  3. package/data/github-copilot-pricing.json +34 -6
  4. package/dist/copilot-usage-studio/browser/chunk-23NLHIOR.js +1 -0
  5. package/dist/copilot-usage-studio/browser/chunk-5JYQJM5G.js +1 -0
  6. package/dist/copilot-usage-studio/browser/chunk-7I2HDBC6.js +1 -0
  7. package/dist/copilot-usage-studio/browser/{chunk-TVSYR63W.js → chunk-OS2XPCVW.js} +2 -2
  8. package/dist/copilot-usage-studio/browser/{chunk-J47KKACI.js → chunk-QMNOUQ2X.js} +1 -1
  9. package/dist/copilot-usage-studio/browser/{chunk-NXH37FKU.js → chunk-RTOXDOOI.js} +1 -1
  10. package/dist/copilot-usage-studio/browser/chunk-TICIZRSM.js +1 -0
  11. package/dist/copilot-usage-studio/browser/chunk-WOIYAEKB.js +4 -0
  12. package/dist/copilot-usage-studio/browser/{chunk-QQOFM3HF.js → chunk-WWU6QMJC.js} +1 -1
  13. package/dist/copilot-usage-studio/browser/chunk-XMVGLQQH.js +1 -0
  14. package/dist/copilot-usage-studio/browser/index.html +2 -2
  15. package/dist/copilot-usage-studio/browser/main-XFPP45VE.js +1 -0
  16. package/dist/copilot-usage-studio/browser/styles-7RDDQXQV.css +1 -0
  17. package/docs/local-deployment.md +92 -17
  18. package/docs/pricing.md +5 -3
  19. package/docs/scanner-api.md +40 -0
  20. package/lib/cli.mjs +15 -1
  21. package/lib/local-runtime.mjs +499 -19
  22. package/lib/scanner-worker.mjs +25 -0
  23. package/package.json +20 -2
  24. package/scripts/pricing-utils.mjs +5 -0
  25. package/scripts/scan-vscode-sessions.mjs +387 -1475
  26. package/scripts/scanner-customization-evidence.mjs +613 -0
  27. package/scripts/scanner-customization-inventory.mjs +1022 -0
  28. package/scripts/scanner-memory.mjs +229 -0
  29. package/scripts/scanner-session-parser.mjs +1237 -0
  30. package/scripts/scanner-traversal.mjs +203 -0
  31. package/scripts/scanner-workspace.mjs +237 -0
  32. package/dist/copilot-usage-studio/browser/chunk-CUKTUQ6W.js +0 -1
  33. package/dist/copilot-usage-studio/browser/chunk-EYAHOEVS.js +0 -1
  34. package/dist/copilot-usage-studio/browser/chunk-FXNLFSUB.js +0 -1
  35. package/dist/copilot-usage-studio/browser/chunk-HJNYITFH.js +0 -1
  36. package/dist/copilot-usage-studio/browser/chunk-KDAJN6DF.js +0 -4
  37. package/dist/copilot-usage-studio/browser/main-TL27ZSEQ.js +0 -1
  38. package/dist/copilot-usage-studio/browser/styles-GZOQ5QIH.css +0 -1
@@ -0,0 +1,203 @@
1
+ import { existsSync, readdirSync } from 'node:fs';
2
+ import { homedir, platform } from 'node:os';
3
+ import { basename, dirname, join, resolve } from 'node:path';
4
+
5
+ export const skippedTraversalDirs = new Set([
6
+ '.angular',
7
+ '.cache',
8
+ '.git',
9
+ '.hg',
10
+ '.next',
11
+ '.nuxt',
12
+ '.pnpm-store',
13
+ '.svn',
14
+ '.turbo',
15
+ '.venv',
16
+ '__pycache__',
17
+ 'bin',
18
+ 'build',
19
+ 'coverage',
20
+ 'dist',
21
+ 'node_modules',
22
+ 'obj',
23
+ 'out',
24
+ 'target',
25
+ 'venv',
26
+ ]);
27
+
28
+ export function defaultCodeUserDirs() {
29
+ const home = homedir();
30
+
31
+ if (platform() === 'win32') {
32
+ const appData = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
33
+ return [join(appData, 'Code', 'User'), join(appData, 'Code - Insiders', 'User')];
34
+ }
35
+
36
+ if (platform() === 'darwin') {
37
+ return [
38
+ join(home, 'Library', 'Application Support', 'Code', 'User'),
39
+ join(home, 'Library', 'Application Support', 'Code - Insiders', 'User'),
40
+ ];
41
+ }
42
+
43
+ return [join(home, '.config', 'Code', 'User'), join(home, '.config', 'Code - Insiders', 'User')];
44
+ }
45
+
46
+ export function listDirs(dir, options = {}) {
47
+ if (!existsSync(dir)) {
48
+ return [];
49
+ }
50
+
51
+ try {
52
+ return readdirSync(dir, { withFileTypes: true })
53
+ .filter((entry) => entry.isDirectory() && !entry.isSymbolicLink())
54
+ .map((entry) => join(dir, entry.name));
55
+ } catch (error) {
56
+ warn(options, `${dir}: directory listing skipped: ${error.message}`);
57
+ return [];
58
+ }
59
+ }
60
+
61
+ export function listFiles(dir, suffix, options = {}) {
62
+ if (!existsSync(dir)) {
63
+ return [];
64
+ }
65
+
66
+ try {
67
+ return readdirSync(dir, { withFileTypes: true })
68
+ .filter((entry) => entry.isFile() && entry.name.endsWith(suffix))
69
+ .map((entry) => join(dir, entry.name));
70
+ } catch (error) {
71
+ warn(options, `${dir}: file listing skipped: ${error.message}`);
72
+ return [];
73
+ }
74
+ }
75
+
76
+ export function listDebugLogFiles(root, options = {}) {
77
+ if (!existsSync(root)) {
78
+ return [];
79
+ }
80
+
81
+ const files = [];
82
+ const pending = [{ path: root, depth: 0 }];
83
+ const maxDepth = Number(options.maxDepth ?? 4);
84
+ const maxDirs = Number(options.maxDirs ?? 2000);
85
+ let visitedDirs = 0;
86
+
87
+ while (pending.length && visitedDirs < maxDirs) {
88
+ const current = pending.pop();
89
+ visitedDirs += 1;
90
+ let entries = [];
91
+ try {
92
+ entries = readdirSync(current.path, { withFileTypes: true });
93
+ } catch (error) {
94
+ warn(options, `${current.path}: debug-log side-file scan skipped: ${error.message}`);
95
+ continue;
96
+ }
97
+ for (const entry of entries) {
98
+ const path = join(current.path, entry.name);
99
+ if (entry.isSymbolicLink()) {
100
+ continue;
101
+ }
102
+ if (entry.isDirectory() && current.depth < maxDepth && !skippedTraversalDirs.has(entry.name)) {
103
+ pending.push({ path, depth: current.depth + 1 });
104
+ } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {
105
+ files.push(path);
106
+ }
107
+ }
108
+ }
109
+ if (pending.length) {
110
+ warn(options, `${root}: debug-log side-file scan capped at ${maxDirs} directories.`);
111
+ }
112
+
113
+ return files.sort();
114
+ }
115
+
116
+ export function listFilesRecursive(root, predicate, limit, options = {}) {
117
+ if (!existsSync(root)) {
118
+ return [];
119
+ }
120
+
121
+ const maxDepth = Number(options.maxDepth ?? 8);
122
+ const maxDirs = Number(options.maxDirs ?? 5000);
123
+ const label = options.label ?? 'recursive';
124
+ const fileLimit = Number(limit ?? 5000);
125
+ const files = [];
126
+ const pending = [{ path: root, depth: 0 }];
127
+ let visitedDirs = 0;
128
+
129
+ while (pending.length && files.length < fileLimit && visitedDirs < maxDirs) {
130
+ const current = pending.pop();
131
+ visitedDirs += 1;
132
+ let entries = [];
133
+
134
+ try {
135
+ entries = readdirSync(current.path, { withFileTypes: true });
136
+ } catch (error) {
137
+ options.onUnreadable?.(current.path, error);
138
+ warn(options, `${current.path}: ${label} directory skipped: ${error.message}`);
139
+ continue;
140
+ }
141
+
142
+ for (const entry of entries) {
143
+ const path = join(current.path, entry.name);
144
+ if (entry.isSymbolicLink()) {
145
+ continue;
146
+ }
147
+ if (entry.isDirectory()) {
148
+ if (current.depth < maxDepth && !skippedTraversalDirs.has(entry.name)) {
149
+ pending.push({ path, depth: current.depth + 1 });
150
+ }
151
+ } else if (entry.isFile() && predicate(path)) {
152
+ files.push(path);
153
+ if (files.length >= fileLimit) {
154
+ warn(options, `${root}: ${label} scan capped at ${fileLimit} files.`);
155
+ break;
156
+ }
157
+ }
158
+ }
159
+ }
160
+ if (pending.length) {
161
+ warn(options, `${root}: ${label} scan capped at ${maxDirs} directories.`);
162
+ }
163
+
164
+ return files;
165
+ }
166
+
167
+ export function workspaceDirsFromUserDir(userDir, options = {}) {
168
+ const workspaceStorage = join(userDir, 'workspaceStorage');
169
+ return listDirs(workspaceStorage, options);
170
+ }
171
+
172
+ export function workspaceDirsForRoot(root, options = {}) {
173
+ if (existsSync(join(root, 'workspace.json'))) {
174
+ return [root];
175
+ }
176
+ if (basename(root) === 'workspaceStorage') {
177
+ return listDirs(root, options);
178
+ }
179
+ return workspaceDirsFromUserDir(root, options);
180
+ }
181
+
182
+ export function userDirForRoot(root) {
183
+ if (existsSync(join(root, 'workspaceStorage'))) {
184
+ return root;
185
+ }
186
+ if (basename(root) === 'workspaceStorage') {
187
+ return dirname(root);
188
+ }
189
+ if (basename(dirname(root)) === 'workspaceStorage') {
190
+ return dirname(dirname(root));
191
+ }
192
+ return null;
193
+ }
194
+
195
+ export function uniqueResolvedRoots(configuredRoots) {
196
+ return [...new Set(configuredRoots.map((root) => resolve(String(root))))];
197
+ }
198
+
199
+ function warn(options, message) {
200
+ if (typeof options.onWarning === 'function') {
201
+ options.onWarning(message);
202
+ }
203
+ }
@@ -0,0 +1,237 @@
1
+ import { existsSync, statSync } from 'node:fs';
2
+ import { basename, join } from 'node:path';
3
+
4
+ export function parseWorkspace(workspaceDir, options = {}, onProgress = () => {}, dependencies = {}) {
5
+ const {
6
+ customizationsFromDebugReferences,
7
+ customizationsFromDiscoveryFolders,
8
+ customizationsFromWorkspace,
9
+ customizationEvidenceFromDebugLogs,
10
+ diagnostics,
11
+ enrichSessionFromWorkspaceState,
12
+ listDirs,
13
+ listFiles,
14
+ memoriesFromRoot,
15
+ readWorkspaceState,
16
+ sessionFromChatSnapshot,
17
+ sessionFromDebugLog,
18
+ workspaceName,
19
+ } = dependencies;
20
+
21
+ assertWorkspaceDependencies(dependencies);
22
+
23
+ const includeCustomizations = options.includeCustomizations !== false;
24
+ const customizationOptions = {
25
+ includeSystemCustomizations: options.includeSystemCustomizations === true,
26
+ customizationDiscovery: options.customizationDiscovery ?? null,
27
+ };
28
+ const customizationEvidenceOptions = options.customizationEvidence ?? {};
29
+ diagnostics.scannedWorkspaces += 1;
30
+ const workspace = workspaceName(workspaceDir);
31
+ const workspaceStartedAt = Date.now();
32
+ const workspaceStartedAtIso = new Date(workspaceStartedAt).toISOString();
33
+ const workspaceProgressBase = {
34
+ workspace,
35
+ workspaceDir,
36
+ workspaceIndex: options.workspaceIndex ?? null,
37
+ workspaceTotal: options.workspaceTotal ?? null,
38
+ };
39
+ const workspaceScan = {
40
+ ...workspaceProgressBase,
41
+ startedAt: workspaceStartedAtIso,
42
+ completedAt: '',
43
+ durationMs: 0,
44
+ debugLogFolders: 0,
45
+ chatSnapshots: 0,
46
+ hasMemoryRoot: false,
47
+ customizationInventory: 0,
48
+ importedSessions: 0,
49
+ importedMemories: 0,
50
+ importedCustomizations: 0,
51
+ lastStage: 'starting',
52
+ };
53
+ if (diagnostics.workspaceScans.length < 500) {
54
+ diagnostics.workspaceScans.push(workspaceScan);
55
+ }
56
+ const progress = (stage, message, extra = {}) => {
57
+ workspaceScan.lastStage = stage;
58
+ onProgress({
59
+ stage,
60
+ message,
61
+ ...workspaceProgressBase,
62
+ elapsedMs: Date.now() - workspaceStartedAt,
63
+ ...extra,
64
+ });
65
+ };
66
+ const debugRoot = join(workspaceDir, 'GitHub.copilot-chat', 'debug-logs');
67
+ const allDebugSessionDirs = listDirs(debugRoot);
68
+ const allChatSessionFiles = listFiles(join(workspaceDir, 'chatSessions'), '.jsonl');
69
+ const incrementalSinceMs = timestampMs(options.incrementalSince);
70
+ const debugSessionDirs = incrementalSinceMs
71
+ ? allDebugSessionDirs.filter((sessionDir) =>
72
+ sourceChangedSince(join(sessionDir, 'main.jsonl'), incrementalSinceMs))
73
+ : allDebugSessionDirs;
74
+ const chatSessionFiles = incrementalSinceMs
75
+ ? allChatSessionFiles.filter((file) => sourceChangedSince(file, incrementalSinceMs))
76
+ : allChatSessionFiles;
77
+ const memoryRoot = join(workspaceDir, 'GitHub.copilot-chat', 'memory-tool', 'memories');
78
+ const hasMemoryRoot = existsSync(memoryRoot);
79
+ workspaceScan.debugLogFolders = allDebugSessionDirs.length;
80
+ workspaceScan.chatSnapshots = allChatSessionFiles.length;
81
+ workspaceScan.changedDebugLogFolders = debugSessionDirs.length;
82
+ workspaceScan.changedChatSnapshots = chatSessionFiles.length;
83
+ workspaceScan.hasMemoryRoot = hasMemoryRoot;
84
+
85
+ if (!allDebugSessionDirs.length && !allChatSessionFiles.length && !hasMemoryRoot) {
86
+ workspaceScan.completedAt = new Date().toISOString();
87
+ workspaceScan.durationMs = Date.now() - workspaceStartedAt;
88
+ workspaceScan.lastStage = 'empty';
89
+ return {
90
+ sessions: [],
91
+ memories: [],
92
+ customizations: [],
93
+ };
94
+ }
95
+
96
+ progress('workspace', `Checking VS Code storage entry for ${workspace}.`, {
97
+ debugLogFolders: allDebugSessionDirs.length,
98
+ chatSnapshots: allChatSessionFiles.length,
99
+ changedDebugLogFolders: debugSessionDirs.length,
100
+ changedChatSnapshots: chatSessionFiles.length,
101
+ hasMemoryRoot,
102
+ });
103
+ progress('workspace-state', `Reading workspace metadata for ${workspace}.`);
104
+ const stateBySessionId =
105
+ debugSessionDirs.length || chatSessionFiles.length ? readWorkspaceState(workspaceDir) : new Map();
106
+ let customizations = [];
107
+ if (includeCustomizations) {
108
+ progress('customizations', `Indexing customizations for ${workspace}.`);
109
+ const customizationWorkspace = customizationsFromWorkspace(workspaceDir, customizationOptions);
110
+ const customizationMap = new Map();
111
+ const strictCustomizationDiscovery = customizationOptions.customizationDiscovery?.strict === true;
112
+ for (const customization of [
113
+ ...customizationWorkspace.customizations,
114
+ ...(strictCustomizationDiscovery ? [] : customizationsFromDiscoveryFolders(debugRoot, workspace, customizationOptions)),
115
+ ...customizationsFromDebugReferences(debugRoot, customizationWorkspace.bases, workspace, customizationOptions),
116
+ ]) {
117
+ customizationMap.set(customization.id, customization);
118
+ }
119
+ const customizationInventory = [...customizationMap.values()];
120
+ workspaceScan.customizationInventory = customizationInventory.length;
121
+ progress(
122
+ 'customization-evidence',
123
+ debugSessionDirs.length
124
+ ? `Checking customization evidence in ${debugSessionDirs.length} debug-log folder${debugSessionDirs.length === 1 ? '' : 's'} for ${workspace}.`
125
+ : `No debug-log evidence available for ${workspace}; customizations are inventory-only.`,
126
+ {
127
+ total: debugSessionDirs.length,
128
+ customizationInventory: customizationInventory.length,
129
+ },
130
+ );
131
+ customizations = customizationEvidenceFromDebugLogs(
132
+ debugRoot,
133
+ customizationInventory,
134
+ workspace,
135
+ workspaceDir,
136
+ onProgress,
137
+ customizationEvidenceOptions,
138
+ );
139
+ workspaceScan.importedCustomizations = customizations.length;
140
+ diagnostics.importedCustomizations += customizations.length;
141
+ }
142
+
143
+ if (debugSessionDirs.length) {
144
+ progress('debug-logs', `Scanning ${debugSessionDirs.length} debug-log folder${debugSessionDirs.length === 1 ? '' : 's'} in ${workspace}.`, {
145
+ total: debugSessionDirs.length,
146
+ });
147
+ }
148
+ const debugSessions = [];
149
+ for (const [index, sessionDir] of debugSessionDirs.entries()) {
150
+ if (index > 0 && index % 25 === 0) {
151
+ progress('debug-logs', `Scanned ${index}/${debugSessionDirs.length} debug-log folders in ${workspace}.`, {
152
+ index,
153
+ total: debugSessionDirs.length,
154
+ });
155
+ }
156
+ const session = sessionFromDebugLog(sessionDir, workspaceDir);
157
+ if (session) {
158
+ debugSessions.push(enrichSessionFromWorkspaceState(session, stateBySessionId));
159
+ }
160
+ }
161
+ const debugIds = new Set(allDebugSessionDirs.map((sessionDir) => basename(sessionDir)));
162
+ diagnostics.importedDebugLogSessions += debugSessions.length;
163
+
164
+ if (chatSessionFiles.length) {
165
+ progress('chat-snapshots', `Scanning ${chatSessionFiles.length} chat snapshot${chatSessionFiles.length === 1 ? '' : 's'} in ${workspace}.`, {
166
+ total: chatSessionFiles.length,
167
+ });
168
+ }
169
+ const chatSessions = [];
170
+ for (const file of chatSessionFiles) {
171
+ const session = sessionFromChatSnapshot(file, workspaceDir);
172
+ if (session && debugIds.has(session.id)) {
173
+ diagnostics.skippedDuplicateChatSnapshots += 1;
174
+ continue;
175
+ }
176
+ if (session) {
177
+ chatSessions.push(enrichSessionFromWorkspaceState(session, stateBySessionId));
178
+ }
179
+ }
180
+ diagnostics.importedChatSnapshotSessions += chatSessions.length;
181
+ const memories = memoriesFromRoot(memoryRoot, 'workspace', workspace);
182
+ workspaceScan.importedSessions = debugSessions.length + chatSessions.length;
183
+ workspaceScan.importedMemories = memories.length;
184
+ workspaceScan.completedAt = new Date().toISOString();
185
+ workspaceScan.durationMs = Date.now() - workspaceStartedAt;
186
+
187
+ progress('workspace-complete', `VS Code storage entry for ${workspace}: imported ${debugSessions.length + chatSessions.length} session${debugSessions.length + chatSessions.length === 1 ? '' : 's'} in ${workspaceScan.durationMs}ms.`, {
188
+ sessions: debugSessions.length + chatSessions.length,
189
+ memories: memories.length,
190
+ customizations: customizations.length,
191
+ durationMs: workspaceScan.durationMs,
192
+ });
193
+
194
+ return {
195
+ sessions: [...debugSessions, ...chatSessions],
196
+ memories,
197
+ customizations,
198
+ };
199
+ }
200
+
201
+
202
+ function timestampMs(value) {
203
+ if (!value) {
204
+ return 0;
205
+ }
206
+ const parsed = Date.parse(String(value));
207
+ return Number.isFinite(parsed) ? parsed : 0;
208
+ }
209
+
210
+ function sourceChangedSince(path, sinceMs) {
211
+ try {
212
+ return statSync(path).mtimeMs > sinceMs;
213
+ } catch {
214
+ return true;
215
+ }
216
+ }
217
+ function assertWorkspaceDependencies(dependencies) {
218
+ for (const name of [
219
+ 'customizationsFromDebugReferences',
220
+ 'customizationsFromDiscoveryFolders',
221
+ 'customizationsFromWorkspace',
222
+ 'customizationEvidenceFromDebugLogs',
223
+ 'diagnostics',
224
+ 'enrichSessionFromWorkspaceState',
225
+ 'listDirs',
226
+ 'listFiles',
227
+ 'memoriesFromRoot',
228
+ 'readWorkspaceState',
229
+ 'sessionFromChatSnapshot',
230
+ 'sessionFromDebugLog',
231
+ 'workspaceName',
232
+ ]) {
233
+ if (!dependencies[name]) {
234
+ throw new TypeError(`parseWorkspace missing dependency: ${name}`);
235
+ }
236
+ }
237
+ }
@@ -1 +0,0 @@
1
- import{a as H,b as $,c as W,d as V,e as j,f as q,g as J,h as K,i as y,m as Q,r as X,s as Y}from"./chunk-FXNLFSUB.js";import{$a as _,Ca as f,Da as w,Fa as M,Ga as v,Ha as c,Ia as t,Ja as n,Ka as x,Na as F,O as U,P as D,Pa as E,Ra as C,Sa as L,Ta as z,U as N,Ua as i,Va as s,Wa as d,Xa as T,Z as S,Za as p,_a as O,a as b,b as k,cb as P,ja as A,ka as o,mb as G,nb as B,rb as Z,sa as R,tb as ee,ub as te,vb as ne,wb as ie,xb as ae,yb as oe}from"./chunk-KDAJN6DF.js";var re=(l,a)=>a.id,ce=(l,a)=>a.value,se=(l,a)=>a.model+":"+a.tier;function pe(l,a){if(l&1&&(t(0,"option",10),i(1),n()),l&2){let e=a.$implicit;c("value",e.id),o(),s(e.label)}}function de(l,a){if(l&1&&(t(0,"option",10),i(1),n()),l&2){let e=a.$implicit;c("value",e.value),o(),s(e.label)}}function ge(l,a){if(l&1){let e=F();t(0,"button",24),E("click",function(){let g=U(e).$implicit,m=C();return D(m.setSelectedAllowancePlan(g.id))}),t(1,"span"),i(2),n(),t(3,"strong"),i(4),p(5,"number"),n(),t(6,"em"),i(7),n()()}if(l&2){let e=a.$implicit,r=C();z("active",r.selectedAllowance().id===e.id),o(2),s(e.period),o(2),s(O(5,5,e.creditsPerUserMonthly)),o(3),d("",e.label," credits/user/month")}}function me(l,a){if(l&1&&(t(0,"em"),i(1),n()),l&2){let e=C().$implicit;o(),s(e.note)}}function ue(l,a){if(l&1&&(i(0),p(1,"number")),l&2){let e=C().$implicit;d(" $",_(1,1,e.cacheWrite,"1.0-3")," ")}}function he(l,a){l&1&&i(0," - ")}function xe(l,a){if(l&1&&(t(0,"span",26),i(1," Direct + fallback "),x(2,"app-help-popover",28),n()),l&2){let e=C(3);o(2),c("text",e.help.pricingFallback)}}function _e(l,a){if(l&1&&(t(0,"span",26),i(1," Fallback row "),x(2,"app-help-popover",28),n()),l&2){let e=C(3);o(2),c("text",e.help.pricingFallback)}}function Ce(l,a){l&1&&(t(0,"span",27),i(1,"Direct match"),n())}function Pe(l,a){if(l&1&&f(0,xe,3,1,"span",26)(1,_e,3,1,"span",26)(2,Ce,2,0,"span",27),l&2){let e=C().$implicit;w(e.usedDirectly&&e.usedAsFallback?0:e.usedAsFallback?1:2)}}function be(l,a){l&1&&(t(0,"span",25),i(1,"Not yet"),n())}function fe(l,a){if(l&1&&(t(0,"div",23)(1,"strong"),i(2),f(3,me,2,1,"em"),n(),t(4,"span"),i(5),n(),t(6,"span"),i(7),n(),t(8,"span"),i(9),n(),t(10,"span"),i(11),t(12,"em"),i(13),n()(),t(14,"span"),i(15),p(16,"number"),n(),t(17,"span"),i(18),p(19,"number"),n(),t(20,"span"),f(21,ue,2,4)(22,he,1,0),n(),t(23,"span"),i(24),p(25,"number"),n(),t(26,"span"),f(27,Pe,3,1)(28,be,2,0,"span",25),n()()),l&2){let e=a.$implicit;o(2),d(" ",e.model," "),o(),w(e.note?3:-1),o(2),s(e.provider),o(2),s(e.releaseStatus),o(2),s(e.category),o(2),d(" ",e.tier," "),o(2),s(e.threshold),o(2),d("$",_(16,12,e.input,"1.0-3")),o(3),d("$",_(19,15,e.cachedInput,"1.0-3")),o(3),w(e.cacheWrite?21:22),o(3),d("$",_(25,18,e.output,"1.0-3")),o(3),w(e.usedByImportedSessions?27:28)}}var le=class l{sessionsInput=S([]);selectedAllowancePlanInput=S("business-standard");usageTimeRange=S("all");set sessions(a){this.sessionsInput.set(a??[])}set selectedAllowancePlan(a){this.selectedAllowancePlanInput.set(a??"business-standard")}selectedAllowancePlanChange=new N;pricingVersion=H;pricingSourceLabel=W;pricingSourceUrl=$;pricingSnapshotDate=V;pricingImportedAt=j;allowanceSourceUrl=J;creditUsd=q;allowancePlans=y;usageTimeOptions=[{value:"all",label:"All imported sessions"},{value:"7d",label:"Last 7 days"},{value:"30d",label:"Last 30 days"},{value:"90d",label:"Last 90 days"}];help={inputTokens:"Normal, non-cached input/context tokens priced at the GitHub input rate. Raw VS Code inputTokens can be higher when cachedTokens are present.",outputTokens:"Generated model response tokens.",cachedInput:"Input/context tokens VS Code reported as cachedTokens. They are part of raw input, but priced with GitHub cached-input rates instead of normal input rates.",cacheWrite:"Provider cache creation tokens when the billing source exposes them. GitHub lists this mainly for Anthropic pricing rows.",pricingFallback:"The raw model name from VS Code did not match a GitHub price row in the local pricing table, so the estimate uses the displayed fallback price row. Treat this as an explicit estimate assumption.",allowance:"Included AI credits for Copilot Business and Enterprise are monthly per assigned license, but GitHub pools them at the organization or enterprise billing entity level.",credit:"GitHub states that 1 AI credit equals $0.01 USD. When VS Code logs GitHub source usage, the app uses that first; otherwise it converts the local token estimate into credits.",usageWindow:"This only filters the imported sessions used by the allowance meter. It does not change the GitHub price table below."};selectedAllowance=P(()=>y.find(a=>a.id===this.selectedAllowancePlanInput())??y[0]);allowanceSessions=P(()=>{let a=this.usageCutoff(this.sessionsInput(),this.usageTimeRange());return this.sessionsInput().filter(e=>!a||new Date(e.startedAt).getTime()>=a)});totalEstimateUsd=P(()=>this.allowanceSessions().reduce((a,e)=>a+X(e),0));totalEstimateCredits=P(()=>this.allowanceSessions().reduce((a,e)=>a+Y(e),0));selectedAllowanceUsage=P(()=>{let a=this.selectedAllowance(),e=this.totalEstimateCredits(),r=a.creditsPerUserMonthly>0?e/a.creditsPerUserMonthly*100:0;return{credits:e,share:r,perUserCredits:a.creditsPerUserMonthly,sessions:this.allowanceSessions().length,totalSessions:this.sessionsInput().length,windowLabel:this.usageTimeOptions.find(g=>g.value===this.usageTimeRange())?.label??"All imported sessions"}});pricingRows=P(()=>Object.entries(K).flatMap(([a,e])=>{let r=u=>{let I=this.sessionsInput().flatMap(h=>h.modelBreakdown).filter(h=>h.pricingModel===a&&(h.pricingTiers?.includes(u)??u===(e.tierLabel??"Default")));return{usedByImportedSessions:I.length>0,usedDirectly:I.some(h=>!this.usesPricingFallback(h.model,h.pricingModel)),usedAsFallback:I.some(h=>this.usesPricingFallback(h.model,h.pricingModel))}},g={model:a,provider:e.provider,releaseStatus:e.releaseStatus,category:e.category,note:e.note},m=e.tierLabel??"Default";return[k(b(b({},g),r(m)),{tier:m,threshold:e.tierThresholdLabel??"All request sizes",input:e.input,cachedInput:e.cachedInput,cacheWrite:e.cacheWrite??0,output:e.output}),...(e.tiers??[]).map(u=>k(b(b({},g),r(u.label)),{tier:u.label,threshold:u.thresholdLabel,input:u.input,cachedInput:u.cachedInput,cacheWrite:u.cacheWrite??e.cacheWrite??0,output:u.output}))]}));setSelectedAllowancePlan(a){if(!y.some(r=>r.id===a))return;let e=a;this.selectedAllowancePlanInput.set(e),this.selectedAllowancePlanChange.emit(e)}setUsageTimeRange(a){this.usageTimeOptions.some(e=>e.value===a)&&this.usageTimeRange.set(a)}usesPricingFallback=Q;usageCutoff(a,e){if(e==="all"||!a.length)return null;let r=e==="7d"?7:e==="30d"?30:90,g=Math.max(...a.map(m=>new Date(m.startedAt).getTime()).filter(Number.isFinite));return Number.isFinite(g)?g-r*24*60*60*1e3:null}static \u0275fac=function(e){return new(e||l)};static \u0275cmp=R({type:l,selectors:[["app-pricing-page"]],inputs:{sessions:"sessions",selectedAllowancePlan:"selectedAllowancePlan"},outputs:{selectedAllowancePlanChange:"selectedAllowancePlanChange"},decls:129,vars:46,consts:[[1,"pricing-page"],[1,"pricing-header"],[1,"eyebrow"],["target","_blank","rel","noreferrer",3,"href"],[1,"pricing-source"],["aria-label","GitHub Copilot AI credit allowance",1,"allowance-panel"],[1,"allowance-copy"],[1,"allowance-control"],["label","Explain AI credit allowance",3,"text"],[3,"ngModelChange","ngModel"],[3,"value"],["label","Explain usage window",3,"text"],[1,"allowance-meter"],["aria-hidden","true",1,"allowance-bar"],["aria-label","Available Copilot allowance plans",1,"allowance-grid"],["type","button",1,"allowance-card",3,"active"],[1,"pricing-note"],[1,"pricing-table"],[1,"pricing-row","pricing-row-heading"],["label","Explain normal input",3,"text"],["label","Explain cached input",3,"text"],["label","Explain cache write",3,"text"],["label","Explain output tokens",3,"text"],[1,"pricing-row"],["type","button",1,"allowance-card",3,"click"],[1,"muted"],[1,"used-pill","fallback-used"],[1,"used-pill"],["label","Explain fallback pricing",3,"text"]],template:function(e,r){e&1&&(t(0,"section",0)(1,"div",1)(2,"div")(3,"p",2),i(4,"Cost inputs"),n(),t(5,"h2"),i(6,"GitHub Copilot prices used by this app"),n(),t(7,"p"),i(8," Evidence page for the rate card, AI-credit conversion, source usage, and token-estimate fallback. "),n()(),t(9,"a",3),i(10,"Open GitHub source"),n()(),t(11,"section",4)(12,"div")(13,"span"),i(14,"Source"),n(),t(15,"strong"),i(16),n()(),t(17,"div")(18,"span"),i(19,"Pricing version"),n(),t(20,"strong"),i(21),n()(),t(22,"div")(23,"span"),i(24,"Source checked"),n(),t(25,"strong"),i(26),p(27,"date"),n()(),t(28,"div")(29,"span"),i(30,"Imported into app"),n(),t(31,"strong"),i(32),p(33,"date"),n()()(),t(34,"section",5)(35,"div",6)(36,"p",2),i(37,"License allowance"),n(),t(38,"h3"),i(39,"AI credits context"),n(),t(40,"p"),i(41," GitHub converts model usage into AI credits at "),t(42,"strong"),i(43),p(44,"number"),n(),i(45,". The meter below compares imported source usage, with token estimates as fallback, against the selected per-license allowance. "),n(),t(46,"a",3),i(47,"Open allowance source"),n()(),t(48,"div",7)(49,"label")(50,"span"),i(51," Selected plan "),x(52,"app-help-popover",8),n(),t(53,"select",9),E("ngModelChange",function(m){return r.setSelectedAllowancePlan(m)}),M(54,pe,2,2,"option",10,re),n()(),t(56,"label")(57,"span"),i(58," Usage window "),x(59,"app-help-popover",11),n(),t(60,"select",9),E("ngModelChange",function(m){return r.setUsageTimeRange(m)}),M(61,de,2,2,"option",10,ce),n()(),t(63,"div",12)(64,"div")(65,"span"),i(66),n(),t(67,"strong"),i(68),p(69,"number"),n(),t(70,"em"),i(71),p(72,"number"),p(73,"number"),n()(),t(74,"div")(75,"span"),i(76,"Monthly allowance"),n(),t(77,"strong"),i(78),p(79,"number"),n()(),t(80,"div")(81,"span"),i(82,"Allowance used"),n(),t(83,"strong"),i(84),p(85,"number"),n()()(),t(86,"div",13),x(87,"span"),n(),t(88,"p"),i(89),n()()(),t(90,"section",14),M(91,ge,8,7,"button",15,re),n(),t(93,"div",16)(94,"strong"),i(95,"Calculation rule"),n(),t(96,"p"),i(97," Per-1M-token GitHub rates are multiplied by imported VS Code token buckets. Normal input is "),t(98,"code"),i(99,"inputTokens - cachedTokens"),n(),i(100," when cached tokens are present. Estimates stay in USD because GitHub prices and AI credits are USD-native; cache write is only priced when a numeric cache-write field is imported. Long-context rates are selected independently for each model call from that call's normal plus cached input. "),n()(),t(101,"div",17)(102,"div",18)(103,"span"),i(104,"Model"),n(),t(105,"span"),i(106,"Provider"),n(),t(107,"span"),i(108,"Status"),n(),t(109,"span"),i(110,"Category"),n(),t(111,"span"),i(112,"Tier"),n(),t(113,"span"),i(114,"Normal input "),x(115,"app-help-popover",19),n(),t(116,"span"),i(117,"Cached input "),x(118,"app-help-popover",20),n(),t(119,"span"),i(120,"Cache write "),x(121,"app-help-popover",21),n(),t(122,"span"),i(123,"Output "),x(124,"app-help-popover",22),n(),t(125,"span"),i(126,"Used"),n()(),M(127,fe,29,21,"div",23,se),n()()),e&2&&(o(9),c("href",r.pricingSourceUrl,A),o(7),s(r.pricingSourceLabel),o(5),s(r.pricingVersion),o(5),s(_(27,25,r.pricingSnapshotDate,"MMM d, y")),o(6),s(_(33,28,r.pricingImportedAt,"MMM d, y")),o(11),d("1 credit = $",_(44,31,r.creditUsd,"1.2-2")," USD"),o(3),c("href",r.allowanceSourceUrl,A),o(6),c("text",r.help.allowance),o(),c("ngModel",r.selectedAllowance().id),o(),v(r.allowancePlans),o(5),c("text",r.help.usageWindow),o(),c("ngModel",r.usageTimeRange()),o(),v(r.usageTimeOptions),o(5),s(r.selectedAllowanceUsage().windowLabel),o(2),d("",_(69,34,r.selectedAllowanceUsage().credits,"1.0-1")," credits"),o(3),T("",O(72,37,r.selectedAllowanceUsage().sessions)," of ",O(73,39,r.selectedAllowanceUsage().totalSessions)," sessions"),o(7),d("",O(79,41,r.selectedAllowance().creditsPerUserMonthly)," credits/user"),o(6),d("",_(85,43,r.selectedAllowanceUsage().share,"1.0-1"),"%"),o(3),L("width",r.selectedAllowanceUsage().share>100?100:r.selectedAllowanceUsage().share,"%"),o(2),T("",r.selectedAllowance().period,". ",r.selectedAllowance().note),o(2),v(r.allowancePlans),o(24),c("text",r.help.inputTokens),o(3),c("text",r.help.cachedInput),o(3),c("text",r.help.cacheWrite),o(3),c("text",r.help.outputTokens),o(3),v(r.pricingRows()))},dependencies:[oe,ie,ae,ne,ee,te,Z,G,B],styles:["[_nghost-%COMP%]{display:block}.pricing-page[_ngcontent-%COMP%]{display:grid;gap:16px}.pricing-header[_ngcontent-%COMP%]{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}.pricing-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{margin:0;color:var(--text-strong);font-size:22px;font-weight:760;letter-spacing:0}.pricing-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:0}.pricing-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%]:not(.eyebrow){max-width:720px;margin-top:6px;color:var(--muted);font-size:12px;line-height:1.45}.pricing-header[_ngcontent-%COMP%] a[_ngcontent-%COMP%]{border:1px solid var(--line-strong);border-radius:999px;padding:7px 10px;color:var(--text);font-size:12px;font-weight:720;text-decoration:none;white-space:nowrap}.pricing-source[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));overflow:hidden;border:1px solid var(--line);border-radius:12px;background:var(--surface);box-shadow:var(--shadow, 0 18px 50px rgba(0, 0, 0, .22))}.pricing-source[_ngcontent-%COMP%] div[_ngcontent-%COMP%]{padding:12px;border-right:1px solid var(--line)}.pricing-source[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:last-child{border-right:0}.pricing-source[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .pricing-row[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .pricing-note[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{color:var(--muted);font-size:12px}.pricing-source[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{display:block;margin-top:5px;color:var(--text);font-weight:760}.pricing-note[_ngcontent-%COMP%]{border:1px solid var(--line);border-left:4px solid var(--accent-2);border-radius:12px;padding:12px 14px;background:var(--surface-soft)}.pricing-note[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong)}.pricing-note[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{max-width:940px;margin:4px 0 0;line-height:1.45}.allowance-panel[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(260px,.85fr) minmax(320px,1.15fr);gap:14px;border:1px solid var(--line);border-radius:14px;padding:14px;background:var(--header-gradient, linear-gradient(135deg, rgba(124, 92, 255, .16), rgba(31, 209, 165, .07)), var(--surface))}.allowance-copy[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{margin:0;color:var(--text-strong);font-size:18px;font-weight:760}.allowance-copy[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .allowance-control[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .allowance-card[_ngcontent-%COMP%] em[_ngcontent-%COMP%], .allowance-card[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:var(--muted);font-size:12px;line-height:1.45}.allowance-copy[_ngcontent-%COMP%] a[_ngcontent-%COMP%]{display:inline-flex;margin-top:8px;color:var(--accent-2);font-size:12px;font-weight:760;text-decoration:none}.allowance-control[_ngcontent-%COMP%]{display:grid;align-content:start;gap:12px}.allowance-control[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{display:grid;gap:6px}.allowance-control[_ngcontent-%COMP%] label[_ngcontent-%COMP%] > span[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-size:12px;font-weight:760}.allowance-control[_ngcontent-%COMP%] select[_ngcontent-%COMP%]{width:100%;border:1px solid var(--line-strong);border-radius:10px;padding:8px 10px;background:var(--control-bg, rgba(5, 12, 22, .55));color:var(--text);font:inherit;font-weight:720}.allowance-meter[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.allowance-meter[_ngcontent-%COMP%] div[_ngcontent-%COMP%]{border:1px solid var(--line);border-radius:10px;padding:10px;background:var(--surface-soft)}.allowance-meter[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{display:block;color:var(--muted);font-size:11px}.allowance-meter[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{display:block;margin-top:3px;color:var(--muted);font-size:11px;font-style:normal}.allowance-meter[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{display:block;margin-top:3px;color:var(--text-strong);font-size:16px;font-weight:760}.allowance-bar[_ngcontent-%COMP%]{height:7px;overflow:hidden;border-radius:999px;background:#6170852e}.allowance-bar[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,var(--accent-2),#ffba4a)}.allowance-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.allowance-card[_ngcontent-%COMP%]{display:grid;gap:3px;border:1px solid var(--line);border-radius:12px;padding:10px;background:var(--surface);color:inherit;font:inherit;text-align:left;cursor:pointer}.allowance-card.active[_ngcontent-%COMP%]{border-color:#1fd1a570;background:#1fd1a517;box-shadow:0 0 0 1px #1fd1a51f inset}.allowance-card[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong);font-size:20px;font-weight:760}.pricing-table[_ngcontent-%COMP%]{overflow-x:auto;border:1px solid var(--line);border-radius:12px;background:var(--surface)}.pricing-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(210px,1.35fr) repeat(3,minmax(100px,.65fr)) minmax(150px,.9fr) repeat(4,minmax(100px,.58fr)) minmax(124px,.7fr);min-width:1240px;border-bottom:1px solid var(--line)}.pricing-row[_ngcontent-%COMP%]:last-child{border-bottom:0}.pricing-row[_ngcontent-%COMP%] > *[_ngcontent-%COMP%]{padding:10px 12px}.pricing-row-heading[_ngcontent-%COMP%]{background:var(--surface-soft);color:var(--muted);font-size:11px;font-weight:720;text-transform:uppercase}.pricing-row[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text);font-size:14px;font-weight:760}.pricing-row[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{display:block;margin-top:4px;color:var(--text);font-size:12px;font-style:normal;font-weight:600}.used-pill[_ngcontent-%COMP%]{display:inline-flex;border:1px solid rgba(31,209,165,.35);border-radius:999px;padding:4px 8px;background:#1fd1a51f;color:var(--success-text, #bbfff0)!important;font-size:12px;font-weight:900;white-space:nowrap}.used-pill.fallback-used[_ngcontent-%COMP%]{border-color:#ffba4a73;background:#ffba4a1f;color:var(--warning-text, #ffe0a0)!important}.muted[_ngcontent-%COMP%]{color:var(--muted)}.eyebrow[_ngcontent-%COMP%]{color:var(--accent-2);font-size:10px;font-weight:760;letter-spacing:.08em;text-transform:uppercase}@media(max-width:900px){.pricing-header[_ngcontent-%COMP%], .pricing-source[_ngcontent-%COMP%]{display:grid}.pricing-source[_ngcontent-%COMP%], .allowance-panel[_ngcontent-%COMP%], .allowance-grid[_ngcontent-%COMP%], .allowance-meter[_ngcontent-%COMP%]{grid-template-columns:1fr}.pricing-source[_ngcontent-%COMP%] div[_ngcontent-%COMP%]{border-right:0;border-bottom:1px solid var(--line)}.pricing-source[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:last-child{border-bottom:0}}.used-pill[_ngcontent-%COMP%]{padding:3px 7px;font-size:11px;font-weight:760}@media(max-width:1100px){.allowance-grid[_ngcontent-%COMP%]{grid-template-columns:repeat(2,minmax(0,1fr))}}.theme-light[_nghost-%COMP%] .pricing-source[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .pricing-source[_ngcontent-%COMP%], .theme-light[_nghost-%COMP%] .pricing-table[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .pricing-table[_ngcontent-%COMP%], .theme-light[_nghost-%COMP%] .pricing-note[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .pricing-note[_ngcontent-%COMP%], .theme-light[_nghost-%COMP%] .allowance-panel[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .allowance-panel[_ngcontent-%COMP%]{box-shadow:var(--shadow-soft)}.theme-light[_nghost-%COMP%] .pricing-source[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .pricing-source[_ngcontent-%COMP%]{background:linear-gradient(180deg,#ffffffc2,#ffffff75),var(--surface)}.theme-light[_nghost-%COMP%] .pricing-note[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .pricing-note[_ngcontent-%COMP%]{background:linear-gradient(135deg,#0c9f830b,#6f5cff05),var(--surface)}.theme-light[_nghost-%COMP%] .allowance-panel[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .allowance-panel[_ngcontent-%COMP%]{border-color:#bdcbdae6}.theme-light[_nghost-%COMP%] .allowance-card[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .allowance-card[_ngcontent-%COMP%], .theme-light[_nghost-%COMP%] .allowance-meter[_ngcontent-%COMP%] div[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .allowance-meter[_ngcontent-%COMP%] div[_ngcontent-%COMP%]{background:#ffffffad}.theme-light[_nghost-%COMP%] .pricing-table[_ngcontent-%COMP%], .theme-light [_nghost-%COMP%] .pricing-table[_ngcontent-%COMP%]{background:var(--surface)}"]})};export{le as PricingPageComponent};
@@ -1 +0,0 @@
1
- import{f as Q}from"./chunk-NXH37FKU.js";import{i as S,r as U,s as W}from"./chunk-FXNLFSUB.js";import{$a as b,Ca as v,Da as O,Ea as T,Fa as P,Ga as h,Ha as g,Ia as i,Ja as o,Ka as F,Na as I,O as E,P as D,Pa as f,Ra as x,Sa as $,Ta as z,U as A,Ua as l,Va as m,Wa as B,Xa as w,Ya as V,Z as y,Za as s,_a as _,cb as C,ka as r,mb as L,nb as R,rb as Y,sa as N,tb as j,ub as H,vb as G,wb as q,xb as J,yb as K}from"./chunk-KDAJN6DF.js";var X=(n,t)=>t.id,ae=(n,t)=>t.key;function ie(n,t){if(n&1&&(i(0,"option",6),l(1),o()),n&2){let e=t.$implicit;g("value",e),r(),m(e==="all"?"All workspaces":e)}}function oe(n,t){if(n&1&&(i(0,"option",6),l(1),o()),n&2){let e=t.$implicit;g("value",e),r(),m(e==="all"?"All models":e)}}function re(n,t){if(n&1&&(i(0,"option",6),l(1),o()),n&2){let e=t.$implicit;g("value",e.id),r(),m(e.label)}}function le(n,t){if(n&1){let e=I();i(0,"button",17),f("click",function(){E(e);let p=x();return D(p.resetScope())}),l(1,"Reset scope"),o()}}function se(n,t){if(n&1&&(l(0),s(1,"number")),n&2){let e=x().$implicit;w(" \xB7 ",_(1,2,e.fallbackCount)," fallback",e.fallbackCount===1?"":"s"," ")}}function pe(n,t){if(n&1){let e=I();i(0,"button",18),f("click",function(){let p=E(e).$implicit,c=x();return D(c.emitOpenSession(p.session))}),i(1,"span",19),l(2),o(),i(3,"strong"),l(4),s(5,"number"),o(),i(6,"em",20),l(7),o(),i(8,"em"),l(9),s(10,"number"),o(),i(11,"i",21),F(12,"b"),o(),i(13,"small",22)(14,"span"),l(15),s(16,"number"),v(17,se,2,4),o(),i(18,"span",23),l(19),o()()()}if(n&2){let e=t.$implicit,a=x();z("primary",e.id==="last-session"),g("disabled",!e.session),r(2),m(e.label),r(2),B("",b(5,14,e.credits,"1.0-2")," credits"),r(3),m(e.period),r(2),w("$",b(10,17,e.usd,"1.2-4")," \xB7 ",e.detail),r(3),$("width",e.allowanceShare>100?100:e.allowanceShare,"%"),r(3),w(" ",b(16,20,e.allowanceShare,"1.0-1"),"% of ",a.selectedAllowance().shortLabel," "),r(2),O(e.fallbackCount?17:-1),r(2),m(e.actionLabel)}}function ce(n,t){if(n&1&&(i(0,"span"),l(1),s(2,"number"),s(3,"number"),o()),n&2){let e=t;r(),w("",_(2,2,e.sourceCount)," source \xB7 ",_(3,4,e.fallbackCount)," fallback")}}function de(n,t){if(n&1&&(l(0),s(1,"number")),n&2){let e=x().$implicit;w(" \xB7 ",_(1,2,e.fallbackCount)," fallback",e.fallbackCount===1?"":"s"," ")}}function ge(n,t){if(n&1){let e=I();i(0,"button",24),f("click",function(){let p=E(e).$implicit,c=x();return D(c.emitOpenSession(p.topSession))}),i(1,"span"),l(2),s(3,"date"),o(),i(4,"strong"),l(5),s(6,"number"),o(),i(7,"em"),l(8),s(9,"number"),s(10,"number"),v(11,de,2,4),o()()}if(n&2){let e=t.$implicit;g("disabled",!e.topSession),r(2),m(b(3,7,e.date,"EEE, MMM d")),r(3),B("",b(6,10,e.credits,"1.0-2")," credits"),r(3),V(" ",_(9,13,e.count)," session",e.count===1?"":"s"," \xB7 $",b(10,15,e.usd,"1.2-4")," "),r(3),O(e.fallbackCount?11:-1)}}var Z=class n{sessionsInput=y([]);allowancePlanInput=y("business-standard");workspaceFilter=y("all");modelFilter=y("all");set sessions(t){this.sessionsInput.set(t??[])}set allowancePlan(t){this.allowancePlanInput.set(t??"business-standard")}allowancePlanChange=new A;openSession=new A;allowancePlans=S;help={scope:"Usage is calculated from imported local VS Code sessions. When VS Code reports Copilot usage units, the app uses those. Otherwise it estimates from token buckets and GitHub model prices.",allowance:"Compares your local imported usage with the included monthly AI credits for the selected Copilot plan."};selectedAllowance=C(()=>S.find(t=>t.id===this.allowancePlanInput())??S[0]);currentAllowancePlan=C(()=>this.selectedAllowance().id);workspaceOptions=C(()=>["all",...[...new Set(this.sessionsInput().map(t=>t.workspace).filter(Boolean))].sort()]);modelOptions=C(()=>["all",...[...new Set(this.sessionsInput().map(t=>t.model).filter(Boolean))].sort()]);scopedSessions=C(()=>this.sessionsInput().filter(t=>(this.workspaceFilter()==="all"||t.workspace===this.workspaceFilter())&&(this.modelFilter()==="all"||t.model===this.modelFilter())));scopeActive=C(()=>this.workspaceFilter()!=="all"||this.modelFilter()!=="all");usageWindows=C(()=>Q(this.scopedSessions(),this.selectedAllowance().creditsPerUserMonthly));dailyRows=C(()=>this.buildDailyRows(this.scopedSessions(),14));sourceCoverage=C(()=>{let t=this.scopedSessions(),e=t.filter(a=>a.sourceUsage).length;return{sourceCount:e,fallbackCount:t.length-e,total:t.length}});setAllowancePlan(t){if(!S.some(a=>a.id===t))return;let e=t;this.allowancePlanInput.set(e),this.allowancePlanChange.emit(e)}setWorkspaceFilter(t){this.workspaceFilter.set(t)}setModelFilter(t){this.modelFilter.set(t)}resetScope(){this.workspaceFilter.set("all"),this.modelFilter.set("all")}emitOpenSession(t){t&&this.openSession.emit(t)}buildDailyRows(t,e){let a=ue(new Date);return Array.from({length:e},(p,c)=>{let k=ee(a,-c),te=ee(k,1),M=t.filter(d=>{let u=Date.parse(d.startedAt);return Number.isFinite(u)&&u>=k.getTime()&&u<te.getTime()}),ne=M.reduce((d,u)=>!d||U(u)>U(d)?u:d,null);return{date:k,key:me(k),credits:M.reduce((d,u)=>d+W(u),0),usd:M.reduce((d,u)=>d+U(u),0),count:M.length,topSession:ne,fallbackCount:M.filter(d=>!d.sourceUsage).length}})}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=N({type:n,selectors:[["app-usage-page"]],inputs:{sessions:"sessions",allowancePlan:"allowancePlan"},outputs:{allowancePlanChange:"allowancePlanChange",openSession:"openSession"},decls:55,vars:15,consts:[[1,"usage-page"],[1,"usage-header"],[1,"eyebrow"],["label","Explain usage scope",3,"text"],[1,"usage-controls"],[3,"ngModelChange","ngModel"],[3,"value"],["label","Explain allowance",3,"text"],[1,"usage-scope"],["type","button"],["aria-label","Usage answer cards",1,"usage-answer-grid"],["type","button",1,"usage-answer-card",3,"primary","disabled"],[1,"usage-panels"],[1,"usage-panel"],[1,"panel-heading"],[1,"daily-usage-list"],["type","button",3,"disabled"],["type","button",3,"click"],["type","button",1,"usage-answer-card",3,"click","disabled"],[1,"usage-card-label"],[1,"usage-card-period"],["aria-hidden","true"],[1,"usage-card-footer"],[1,"usage-card-action"],["type","button",3,"click","disabled"]],template:function(e,a){if(e&1&&(i(0,"section",0)(1,"header",1)(2,"div")(3,"p",2),l(4,"Usage home"),o(),i(5,"h2"),l(6,"Your Copilot usage"),o(),i(7,"p"),l(8," Today, this week, this month, and recent activity across imported VS Code sessions. "),F(9,"app-help-popover",3),o()(),i(10,"div",4)(11,"label")(12,"span"),l(13,"Workspace"),o(),i(14,"select",5),f("ngModelChange",function(c){return a.setWorkspaceFilter(c)}),P(15,ie,2,2,"option",6,T),o()(),i(17,"label")(18,"span"),l(19,"Model"),o(),i(20,"select",5),f("ngModelChange",function(c){return a.setModelFilter(c)}),P(21,oe,2,2,"option",6,T),o()(),i(23,"label")(24,"span"),l(25," Monthly allowance "),F(26,"app-help-popover",7),o(),i(27,"select",5),f("ngModelChange",function(c){return a.setAllowancePlan(c)}),P(28,re,2,2,"option",6,X),o()()()(),i(30,"div",8)(31,"span"),l(32),s(33,"number"),s(34,"number"),o(),i(35,"span"),l(36),o(),i(37,"span"),l(38),o(),v(39,le,2,0,"button",9),o(),i(40,"section",10),P(41,pe,20,23,"button",11,X),o(),i(43,"section",12)(44,"article",13)(45,"div",14)(46,"div")(47,"h3"),l(48,"Recent days"),o(),i(49,"p"),l(50,"Local imported usage by calendar day."),o()(),v(51,ce,4,6,"span"),o(),i(52,"div",15),P(53,ge,12,18,"button",16,ae),o()()()()),e&2){let p;r(9),g("text",a.help.scope),r(5),g("ngModel",a.workspaceFilter()),r(),h(a.workspaceOptions()),r(5),g("ngModel",a.modelFilter()),r(),h(a.modelOptions()),r(5),g("text",a.help.allowance),r(),g("ngModel",a.currentAllowancePlan()),r(),h(a.allowancePlans),r(4),w("",_(33,11,a.scopedSessions().length)," of ",_(34,13,a.sessionsInput().length)," sessions"),r(4),m(a.workspaceFilter()==="all"?"All workspaces":a.workspaceFilter()),r(2),m(a.modelFilter()==="all"?"All models":a.modelFilter()),r(),O(a.scopeActive()?39:-1),r(2),h(a.usageWindows()),r(10),O((p=a.sourceCoverage())?51:-1,p),r(2),h(a.dailyRows())}},dependencies:[K,q,J,G,j,H,Y,L,R],styles:["[_nghost-%COMP%]{display:block}.usage-page[_ngcontent-%COMP%]{display:grid;gap:12px}.usage-header[_ngcontent-%COMP%]{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;border:1px solid color-mix(in srgb,var(--accent-2) 24%,var(--line));border-radius:18px;padding:16px;background:var(--header-gradient);box-shadow:var(--shadow)}.eyebrow[_ngcontent-%COMP%]{margin:0;color:var(--muted-2);font-size:10px;font-weight:820;letter-spacing:.08em;text-transform:uppercase}.usage-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{margin:3px 0 0;color:var(--text-strong);font-size:26px;font-weight:820;letter-spacing:0}.usage-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px;max-width:720px;margin:7px 0 0;color:var(--muted);font-size:13px;line-height:1.45}.usage-controls[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(3,minmax(150px,1fr));gap:8px;width:min(720px,58vw)}.usage-controls[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{display:grid;gap:6px;min-width:0;color:var(--muted);font-size:11px;font-weight:760}.usage-controls[_ngcontent-%COMP%] label[_ngcontent-%COMP%] > span[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px}.usage-controls[_ngcontent-%COMP%] select[_ngcontent-%COMP%]{width:100%;min-height:34px;border:1px solid var(--line);border-radius:9px;padding:7px 10px;background:var(--surface-soft);color:var(--text);font:inherit;font-size:13px;font-weight:760}.usage-scope[_ngcontent-%COMP%]{display:flex;flex-wrap:wrap;align-items:center;gap:7px;color:var(--muted);font-size:11px}.usage-scope[_ngcontent-%COMP%] > span[_ngcontent-%COMP%], .usage-scope[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{border:1px solid var(--line);border-radius:999px;padding:4px 8px;background:var(--surface-soft)}.usage-scope[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{color:var(--accent);font:inherit;font-weight:800;cursor:pointer}.usage-answer-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:9px}.usage-answer-card[_ngcontent-%COMP%], .usage-panel[_ngcontent-%COMP%]{border:1px solid var(--line);border-radius:15px;background:var(--surface);box-shadow:var(--shadow-soft)}.usage-answer-card[_ngcontent-%COMP%]{display:grid;gap:6px;min-width:0;padding:13px;color:var(--text);text-align:left;cursor:pointer}.usage-answer-card.primary[_ngcontent-%COMP%]{border-color:#0c9f8347;background:linear-gradient(135deg,#0c9f831f,#6f5cff0d),var(--surface)}.usage-answer-card[_ngcontent-%COMP%]:disabled{cursor:default;opacity:.72}.usage-answer-card[_ngcontent-%COMP%]:hover:not(:disabled){border-color:color-mix(in srgb,var(--accent) 42%,var(--line));transform:translateY(-1px)}.usage-answer-card[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .usage-answer-card[_ngcontent-%COMP%] em[_ngcontent-%COMP%], .usage-answer-card[_ngcontent-%COMP%] small[_ngcontent-%COMP%], .daily-usage-list[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .daily-usage-list[_ngcontent-%COMP%] em[_ngcontent-%COMP%], .usage-panel[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .usage-panel[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .panel-heading[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .panel-heading[_ngcontent-%COMP%] > span[_ngcontent-%COMP%]{color:var(--muted);font-size:12px;font-style:normal;line-height:1.35}.usage-answer-card[_ngcontent-%COMP%] .usage-card-label[_ngcontent-%COMP%]{color:var(--muted-2);font-size:10px;font-weight:820;letter-spacing:.08em;text-transform:uppercase}.usage-answer-card[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong);font-size:21px;font-weight:820;line-height:1.05;overflow-wrap:anywhere}.usage-card-period[_ngcontent-%COMP%]{color:var(--text)!important;font-size:12px!important;font-weight:760}.usage-answer-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%]{display:block;width:100%;height:5px;overflow:hidden;border-radius:999px;background:#61708524}.usage-answer-card[_ngcontent-%COMP%] b[_ngcontent-%COMP%]{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,var(--accent),var(--accent-2))}.usage-card-footer[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:8px}.usage-card-footer[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{min-width:0}.usage-card-action[_ngcontent-%COMP%]{flex:0 0 auto;color:var(--accent-strong, var(--accent))!important;font-size:11px!important;font-weight:820}.usage-answer-card[_ngcontent-%COMP%]:disabled .usage-card-action[_ngcontent-%COMP%]{color:var(--muted-2)!important}.usage-panels[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr;gap:12px;align-items:start}.usage-panel[_ngcontent-%COMP%]{display:grid;gap:10px;padding:13px}.panel-heading[_ngcontent-%COMP%]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.panel-heading[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .usage-panel[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{margin:0;color:var(--text-strong);font-size:16px;font-weight:800}.panel-heading[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:3px 0 0}.panel-heading[_ngcontent-%COMP%] > span[_ngcontent-%COMP%]{flex:0 0 auto;border:1px solid var(--line);border-radius:999px;padding:4px 8px;background:var(--surface-soft);font-weight:760}.daily-usage-list[_ngcontent-%COMP%]{display:grid;gap:6px}.daily-usage-list[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(120px,.45fr) minmax(110px,.35fr) minmax(0,1fr);gap:10px;align-items:center;border:1px solid var(--line);border-radius:10px;padding:8px 10px;background:var(--surface-soft);color:var(--text);text-align:left;cursor:pointer}.daily-usage-list[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:disabled{cursor:default;opacity:.64}.daily-usage-list[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:hover:not(:disabled){border-color:var(--line-strong)}.daily-usage-list[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong);font-size:14px;font-weight:800}@media(max-width:1200px){.usage-answer-grid[_ngcontent-%COMP%]{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(max-width:850px){.usage-header[_ngcontent-%COMP%], .panel-heading[_ngcontent-%COMP%]{display:grid}.usage-controls[_ngcontent-%COMP%]{grid-template-columns:1fr;width:100%}.usage-answer-grid[_ngcontent-%COMP%]{grid-template-columns:repeat(2,minmax(0,1fr))}.daily-usage-list[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{grid-template-columns:1fr;gap:4px}}@media(max-width:560px){.usage-answer-grid[_ngcontent-%COMP%]{grid-template-columns:1fr}}"]})};function ue(n){return new Date(n.getFullYear(),n.getMonth(),n.getDate())}function ee(n,t){let e=new Date(n);return e.setDate(e.getDate()+t),e}function me(n){let t=n.getFullYear(),e=String(n.getMonth()+1).padStart(2,"0"),a=String(n.getDate()).padStart(2,"0");return`${t}-${e}-${a}`}export{Z as UsagePageComponent};
@@ -1 +0,0 @@
1
- import{a as s,b as l}from"./chunk-KDAJN6DF.js";var i={version:"github-copilot-usage-pricing-2026-06-14",sourceUrl:"https://docs.github.com/en/copilot/reference/copilot-billing/models-and-pricing",sourceLabel:"GitHub Docs: Models and pricing for GitHub Copilot",snapshotDate:"2026-06-14",importedAt:"2026-06-14",fallbackModel:"GPT-5.4",models:{"GPT-5 mini":{provider:"OpenAI",releaseStatus:"GA",category:"Lightweight",input:.25,cachedInput:.025,output:2},"GPT-5.3-Codex":{provider:"OpenAI",releaseStatus:"GA",category:"Powerful",input:1.75,cachedInput:.175,output:14},"GPT-5.4":{provider:"OpenAI",releaseStatus:"GA",category:"Versatile",input:2.5,cachedInput:.25,output:15,tierLabel:"Default",tierThresholdLabel:"Up to 272K input tokens",tiers:[{id:"long-context",label:"Long context",thresholdInputTokensExclusive:272e3,thresholdLabel:"Over 272K input tokens",input:5,cachedInput:.5,output:22.5}]},"GPT-5.4 mini":{provider:"OpenAI",releaseStatus:"GA",category:"Lightweight",input:.75,cachedInput:.075,output:4.5},"GPT-5.4 nano":{provider:"OpenAI",releaseStatus:"GA",category:"Lightweight",input:.2,cachedInput:.02,output:1.25},"GPT-5.5":{provider:"OpenAI",releaseStatus:"GA",category:"Powerful",input:5,cachedInput:.5,output:30,tierLabel:"Default",tierThresholdLabel:"Up to 272K input tokens",tiers:[{id:"long-context",label:"Long context",thresholdInputTokensExclusive:272e3,thresholdLabel:"Over 272K input tokens",input:10,cachedInput:1,output:45}]},"Claude Haiku 4.5":{provider:"Anthropic",releaseStatus:"GA",category:"Versatile",input:1,cachedInput:.1,cacheWrite:1.25,output:5},"Claude Sonnet 4":{provider:"Anthropic",releaseStatus:"GA",category:"Versatile",input:3,cachedInput:.3,cacheWrite:3.75,output:15},"Claude Sonnet 4.5":{provider:"Anthropic",releaseStatus:"GA",category:"Versatile",input:3,cachedInput:.3,cacheWrite:3.75,output:15},"Claude Sonnet 4.6":{provider:"Anthropic",releaseStatus:"GA",category:"Versatile",input:3,cachedInput:.3,cacheWrite:3.75,output:15},"Claude Opus 4.5":{provider:"Anthropic",releaseStatus:"GA",category:"Powerful",input:5,cachedInput:.5,cacheWrite:6.25,output:25},"Claude Opus 4.6":{provider:"Anthropic",releaseStatus:"GA",category:"Powerful",input:5,cachedInput:.5,cacheWrite:6.25,output:25},"Claude Opus 4.7":{provider:"Anthropic",releaseStatus:"GA",category:"Powerful",input:5,cachedInput:.5,cacheWrite:6.25,output:25},"Claude Opus 4.8":{provider:"Anthropic",releaseStatus:"GA",category:"Powerful",input:5,cachedInput:.5,cacheWrite:6.25,output:25},"Claude Fable 5":{provider:"Anthropic",releaseStatus:"GA",category:"Powerful",input:10,cachedInput:1,cacheWrite:12.5,output:50,note:"GitHub currently marks this model as unavailable"},"Gemini 2.5 Pro":{provider:"Google",releaseStatus:"GA",category:"Powerful",input:1.25,cachedInput:.125,output:10},"Gemini 3 Flash":{provider:"Google",releaseStatus:"Public preview",category:"Lightweight",input:.5,cachedInput:.05,output:3},"Gemini 3.1 Pro":{provider:"Google",releaseStatus:"Public preview",category:"Powerful",input:2,cachedInput:.2,output:12,tierLabel:"Default",tierThresholdLabel:"Up to 200K input tokens",tiers:[{id:"long-context",label:"Long context",thresholdInputTokensExclusive:2e5,thresholdLabel:"Over 200K input tokens",input:4,cachedInput:.4,output:18}]},"Gemini 3.5 Flash":{provider:"Google",releaseStatus:"GA",category:"Lightweight",input:1.5,cachedInput:.15,output:9},"Raptor mini":{provider:"Fine-tuned (GitHub)",releaseStatus:"Public preview",category:"Versatile",input:.25,cachedInput:.025,output:2},"MAI-Code-1-Flash":{provider:"Microsoft",releaseStatus:"GA",category:"Lightweight",input:.75,cachedInput:.075,output:4.5}}};var v=i.version,U=i.sourceUrl,M=i.sourceLabel,_=i.snapshotDate,E=i.importedAt,P=i.fallbackModel,x=.01,O="https://docs.github.com/en/copilot/concepts/billing/usage-based-billing-for-organizations-and-enterprises",c=i.models,R=[{id:"business-standard",label:"Copilot Business",shortLabel:"Business",creditsPerUserMonthly:1900,period:"Standard monthly allowance",note:"Included AI credits are pooled at the billing entity level."},{id:"enterprise-standard",label:"Copilot Enterprise",shortLabel:"Enterprise",creditsPerUserMonthly:3900,period:"Standard monthly allowance",note:"Included AI credits are pooled at the billing entity level."},{id:"business-promo",label:"Copilot Business promo",shortLabel:"Business promo",creditsPerUserMonthly:3e3,period:"Existing-customer promo, Jun 1-Sep 1 2026",note:"GitHub documents this temporary higher allowance for existing Business customers."},{id:"enterprise-promo",label:"Copilot Enterprise promo",shortLabel:"Enterprise promo",creditsPerUserMonthly:7e3,period:"Existing-customer promo, Jun 1-Sep 1 2026",note:"GitHub documents this temporary higher allowance for existing Enterprise customers."}];function h(e){return String(e??"").replace(/^copilot\//i,"").toLowerCase().replace(/[^a-z0-9]+/g," ").trim().replace(/\s+/g," ")}function g(e){let t=String(e??"").replace(/^copilot\//i,"").trim(),n=h(t),r=Object.keys(c);return r.find(o=>h(o)===n)??r.find(o=>n.includes(h(o)))??(t||"Unknown model")}function A(e){let t=g(e);return c[t]?t:P}function T(e){return c[e||""]??c[P]}function k(e,t){let n=T(e),r=Math.max(0,t.input)+Math.max(0,t.cachedInput),o=[...n.tiers??[]].sort((u,a)=>a.thresholdInputTokensExclusive-u.thresholdInputTokensExclusive).find(u=>r>u.thresholdInputTokensExclusive);return o?l(s(s({},n),o),{tiers:n.tiers}):n}function p(e,t){let n=g(e);return(t||A(n))!==n||!c[n]}function S(e,t){let n=g(e),r=t||A(n);return p(n,r)?`${n||"Unknown model"} is priced with the ${r} row because that raw model id is not in the local GitHub pricing table.`:"This model matched a GitHub price row directly."}function D(e,t){let n=e.pricingModel||e.model,r=k(n,e.tokens),o=e.costBreakdown?.inputUsd??d(e.tokens.input,r.input),u=e.costBreakdown?.cachedInputUsd??d(e.tokens.cachedInput,r.cachedInput),a=e.costBreakdown?.cacheWriteUsd??d(e.tokens.cacheWrite,r.cacheWrite??0),m=e.costBreakdown?.outputUsd??d(e.tokens.output,r.output),I=o+u+a+m,f=e.pricingTiers?.length?e.pricingTiers:[r.label??r.tierLabel??"Default"];return l(s({},e),{provider:r.provider,releaseStatus:r.releaseStatus,category:r.category,inputRate:r.input,cachedInputRate:r.cachedInput,cacheWriteRate:r.cacheWrite??0,outputRate:r.output,inputUsd:o,cachedInputUsd:u,cacheWriteUsd:a,outputUsd:m,totalUsd:I,share:t>0?I/t*100:0,usesFallbackPrice:p(e.model,n),pricingTierLabel:f.join(" + "),hasMixedPricingTiers:f.length>1})}function d(e,t){return e/1e6*t}function L(e){return e.input+e.cachedInput+e.cacheWrite+e.output}function N(e){return L(e.tokens)}function H(e){return b(e.sourceUsage?.usd)??e.cost.usd}function z(e){return b(e.sourceUsage?.credits)??e.cost.usd/x}function K(e){return e.sourceUsage?"GitHub usage":"Estimate fallback"}function V(e){return b(e.sourceUsage?.usd)}function j(e,t){return e===0?null:(t-e)/e*100}var J=p;function $(e,t){return e.size!==t.size?!0:[...e].some(n=>!t.has(n))}function b(e){return typeof e=="number"&&Number.isFinite(e)?e:null}export{v as a,U as b,M as c,_ as d,E as e,x as f,O as g,c as h,R as i,h as j,A as k,k as l,p as m,S as n,D as o,L as p,N as q,H as r,z as s,K as t,V as u,j as v,J as w,$ as x};
@@ -1 +0,0 @@
1
- import{a as N}from"./chunk-TVSYR63W.js";import{$a as w,Ca as u,Da as y,Ea as F,Fa as O,Ga as S,Ha as f,Ia as r,J as k,Ja as n,Ka as T,Na as b,O as C,P as M,Pa as _,Ra as c,Ta as V,U as E,Ua as o,Va as p,Wa as x,Xa as P,Z as h,Za as d,_a as g,cb as v,ka as l,mb as z,nb as B,rb as D,sa as I,sb as j,tb as q,ub as R,vb as $,wb as A,xb as L,yb as K}from"./chunk-KDAJN6DF.js";var H=(a,t)=>t.id;function Q(a,t){if(a&1&&(r(0,"option",15),o(1),n()),a&2){let e=t.$implicit;f("value",e),l(),p(e==="all"?"All workspaces":e)}}function G(a,t){if(a&1){let e=b();r(0,"button",23),_("click",function(){C(e);let s=c(2);return M(s.resetFilters())}),o(1,"Reset"),n()}}function J(a,t){if(a&1&&(r(0,"em"),o(1),d(2,"number"),n()),a&2){let e=c().$implicit;l(),P(" ",g(2,2,e.recalls==null?null:e.recalls.length)," ",(e.recalls==null?null:e.recalls.length)===1?"read":"reads"," ")}}function U(a,t){if(a&1&&(r(0,"time"),o(1),d(2,"date"),n()),a&2){let e=c().$implicit;l(),p(w(2,1,e.modifiedAt,"MMM d"))}}function X(a,t){if(a&1){let e=b();r(0,"button",24),_("click",function(){let s=C(e).$implicit,m=c(2);return M(m.selectMemory(s))}),r(1,"span",25),o(2),n(),r(3,"span",26)(4,"small"),o(5),n(),r(6,"strong"),o(7),n()(),r(8,"span",27)(9,"b"),o(10),n(),u(11,J,3,4,"em")(12,U,3,4,"time"),n()()}if(a&2){let e=t.$implicit,i=c(2);V("active",i.selectedMemory().id===e.id)("plan",e.kind==="plan"),l(2),x(" ",e.kind==="plan"?"P":"M"," "),l(3),p(i.fileName(e)),l(2),p(e.title),l(3),p(e.kind==="plan"?"Plan":i.scopeLabel(e.scope)),l(),y(e.recalls!=null&&e.recalls.length?11:12)}}function Y(a,t){if(a&1){let e=b();r(0,"button",23),_("click",function(){C(e);let s=c(),m=c(2);return M(m.emitOpenSession(s))}),o(1),n()}a&2&&(l(),x(" Created in: ",t.title," "))}function Z(a,t){if(a&1&&(r(0,"span"),o(1),n()),a&2){let e=c();l(),x("Session ",e.sessionId.slice(0,8))}}function ee(a,t){if(a&1&&(r(0,"p",34),o(1),n()),a&2){let e=c(3);l(),p(e.actionStatus())}}function te(a,t){if(a&1){let e=b();r(0,"button",23),_("click",function(){C(e);let s=c().$implicit,m=c(4);return M(m.emitRecallSession(s.sessionId))}),o(1),n()}a&2&&(l(),x(" ",t.title," "))}function ne(a,t){if(a&1&&(r(0,"span"),o(1),n()),a&2){let e=c().$implicit;l(),x("Session ",e.sessionId.slice(0,8))}}function oe(a,t){if(a&1&&(o(0),d(1,"number")),a&2){let e=c();x(" \xB7 ",g(1,1,e.cachedInputTokens)," cached ")}}function ie(a,t){if(a&1&&(r(0,"span"),o(1),d(2,"number"),u(3,oe,2,3),n()),a&2){let e=t,i=c().$implicit,s=c(4);l(),P(" ",s.recallRequestLabel(i)," \xB7 ",g(2,3,e.inputTokens)," input "),l(2),y(e.cachedInputTokens?3:-1)}}function re(a,t){if(a&1&&(r(0,"article",40)(1,"div")(2,"time"),o(3),d(4,"date"),n(),u(5,te,2,1,"button",20)(6,ne,2,1,"span"),n(),r(7,"div",42)(8,"span"),o(9),d(10,"number"),n(),u(11,ie,4,5,"span"),n()()),a&2){let e,i,s=t.$implicit,m=c(4);l(3),p(w(4,4,s.timestamp,"medium")),l(2),y((e=m.recallSession(s.sessionId))?5:6,e),l(4),x("",g(10,7,s.returnedCharacterCount)," characters loaded"),l(2),y((i=s.followingModelCall)?11:-1,i)}}function ae(a,t){if(a&1&&(r(0,"section",35)(1,"header")(2,"div")(3,"span",29),o(4,"Observed use"),n(),r(5,"h4"),o(6),d(7,"number"),n()(),r(8,"p"),o(9,"These are explicit memory reads recorded by VS Code."),n()(),r(10,"div",39),O(11,re,12,9,"article",40,H),n(),r(13,"p",41),o(14," Request totals include the complete prompt and context, not only this memory. "),n()()),a&2){let e=c();l(6),P(" Read ",g(7,2,e.recalls==null?null:e.recalls.length)," ",(e.recalls==null?null:e.recalls.length)===1?"time":"times"," "),l(5),S(e.recalls)}}function le(a,t){if(a&1){let e=b();r(0,"article",22)(1,"header",28)(2,"div")(3,"span",29),o(4),n(),r(5,"h3"),o(6),n(),r(7,"p"),o(8),d(9,"date"),n()(),r(10,"div",30)(11,"button",23),_("click",function(){let s=C(e),m=c(2);return M(m.copyContent(s))}),o(12,"Copy"),n(),r(13,"button",23),_("click",function(){let s=C(e),m=c(2);return M(m.runMemoryAction(s,"open"))}),o(14,"Open file"),n(),r(15,"button",23),_("click",function(){let s=C(e),m=c(2);return M(m.runMemoryAction(s,"reveal"))}),o(16,"Show in folder"),n(),r(17,"button",23),_("click",function(){let s=C(e),m=c(2);return M(m.copyPath(s))}),o(18,"Copy path"),n()()(),r(19,"div",31)(20,"span",32)(21,"b"),o(22),n(),o(23," scope "),T(24,"app-help-popover",33),n(),r(25,"span")(26,"b"),o(27),d(28,"number"),n(),o(29," characters"),n(),r(30,"span")(31,"b"),o(32),d(33,"number"),n(),o(34," lines"),n(),r(35,"span")(36,"b"),o(37),n()(),u(38,Y,2,1,"button",20)(39,Z,2,1,"span"),n(),u(40,ee,2,1,"p",34),u(41,ae,15,4,"section",35),r(42,"details",36)(43,"summary")(44,"span"),o(45,"Markdown source"),n(),r(46,"small"),o(47),d(48,"number"),d(49,"number"),n()(),r(50,"pre",37),o(51),n()(),r(52,"footer",38)(53,"span"),o(54,"Local file"),n(),r(55,"code"),o(56),n()()()}if(a&2){let e,i=t,s=c(2);l(4),x(" ",i.kind==="plan"?"Saved plan":s.scopeLabel(i.scope)+" memory"," "),l(2),p(i.title),l(2),P(" ",i.workspace||"Available across workspaces"," \xB7 updated ",w(9,16,i.modifiedAt,"medium")," "),l(14),p(s.scopeLabel(i.scope)),l(2),f("text",s.scopeHelp(i.scope)),l(3),p(g(28,19,i.characterCount)),l(5),p(g(33,21,i.lineCount)),l(5),p(s.fileName(i)),l(),y((e=s.linkedSession(i))?38:i.sessionId?39:-1,e),l(2),y(s.actionStatus()?40:-1),l(),y(i.recalls!=null&&i.recalls.length?41:-1),l(6),P("",g(48,23,i.lineCount)," lines \xB7 ",g(49,25,i.characterCount)," characters"),l(4),p(i.content),l(5),p(i.sourcePath)}}function se(a,t){if(a&1&&(r(0,"section",16)(1,"aside",18)(2,"div",19)(3,"span"),o(4),d(5,"number"),n(),u(6,G,2,0,"button",20),n(),O(7,X,13,9,"button",21,H),n(),u(9,le,57,27,"article",22),n()),a&2){let e,i=c();l(4),x("",g(5,3,i.filteredMemories().length)," shown"),l(2),y(i.query()||i.scopeFilter()!=="all"||i.kindFilter()!=="all"||i.workspaceFilter()!=="all"?6:-1),l(),S(i.filteredMemories()),l(2),y((e=i.selectedMemory())?9:-1,e)}}function ce(a,t){if(a&1){let e=b();r(0,"button",23),_("click",function(){C(e);let s=c(2);return M(s.resetFilters())}),o(1,"Reset filters"),n()}}function me(a,t){if(a&1&&(r(0,"section",17)(1,"h3"),o(2),n(),r(3,"p"),o(4),n(),u(5,ce,2,0,"button",20),n()),a&2){let e=c();l(2),p(e.memoriesInput().length?"No memories match these filters":"No Copilot memories found"),l(2),x(" ",e.memoriesInput().length?"Try a broader search or reset the filters.":"Create a saved memory or plan in VS Code, then refresh the local scan."," "),l(),y(e.memoriesInput().length?5:-1)}}var W=class a{http=k(N);memoriesInput=h([]);sessionsInput=h([]);query=h("");scopeFilter=h("all");kindFilter=h("all");workspaceFilter=h("all");selectedId=h(null);actionStatus=h("");set memories(t){let e=t??[];this.memoriesInput.set(e),(!this.selectedId()||!e.some(i=>i.id===this.selectedId()))&&this.selectedId.set(e[0]?.id??null)}set sessions(t){this.sessionsInput.set(t??[])}openSession=new E;workspaceOptions=v(()=>["all",...[...new Set(this.memoriesInput().map(t=>t.workspace).filter(Boolean))].sort()]);filteredMemories=v(()=>{let t=this.query().trim().toLowerCase();return this.memoriesInput().filter(e=>(!t||[e.title,e.excerpt,e.content,e.relativePath,e.sourcePath,this.fileName(e),e.workspace,e.scope,e.kind].join(" ").toLowerCase().includes(t))&&(this.scopeFilter()==="all"||e.scope===this.scopeFilter())&&(this.kindFilter()==="all"||e.kind===this.kindFilter())&&(this.workspaceFilter()==="all"||e.workspace===this.workspaceFilter()))});selectedMemory=v(()=>{let t=this.filteredMemories();return t.find(e=>e.id===this.selectedId())??t[0]??null});summary=v(()=>{let t=this.memoriesInput();return{total:t.length,plans:t.filter(e=>e.kind==="plan").length,recalls:t.reduce((e,i)=>e+(i.recalls?.length??0),0),repositories:new Set(t.map(e=>e.workspace).filter(Boolean)).size}});recallSession(t){return this.sessionsInput().find(e=>e.id===t)??null}emitRecallSession(t){let e=this.recallSession(t);e&&this.openSession.emit(e)}recallRequestLabel(t){let e=t.followingModelCall?.number,i=e?`request ${e}`:"request";return t.sourceLog==="main.jsonl"?`Before model ${i}`:`Before subagent model ${i}`}selectMemory(t){this.selectedId.set(t.id),this.actionStatus.set("")}setScopeFilter(t){this.scopeFilter.set(t),this.actionStatus.set(""),this.ensureVisibleSelection()}setKindFilter(t){this.kindFilter.set(t),this.actionStatus.set(""),this.ensureVisibleSelection()}setWorkspaceFilter(t){this.workspaceFilter.set(t),this.actionStatus.set(""),this.ensureVisibleSelection()}setQuery(t){this.query.set(t),this.actionStatus.set(""),this.ensureVisibleSelection()}resetFilters(){this.query.set(""),this.scopeFilter.set("all"),this.kindFilter.set("all"),this.workspaceFilter.set("all"),this.ensureVisibleSelection()}fileName(t){return(t.relativePath||t.sourcePath).split(/[\\/]+/).filter(Boolean).at(-1)??t.title}scopeHelp(t){return{session:"Session-scoped memory is tied to one Copilot session. It is useful for saved plans or temporary research from that run.",repository:"Repository memory is saved for a workspace repository and can be available to future Copilot sessions in that workspace.",workspace:"Workspace memory belongs to this VS Code workspace but is not clearly tied to one repository or session.",global:"Global memory is stored in VS Code user storage and can apply across workspaces on this machine."}[t]}ensureVisibleSelection(){let t=this.filteredMemories();if(!t.length){this.selectedId.set(null);return}t.some(e=>e.id===this.selectedId())||this.selectedId.set(t[0].id)}linkedSession(t){return t.sessionId?this.sessionsInput().find(e=>e.id===t.sessionId)??null:null}emitOpenSession(t){let e=this.linkedSession(t);e&&this.openSession.emit(e)}runMemoryAction(t,e){this.actionStatus.set(e==="open"?"Opening file\u2026":"Showing file\u2026"),this.http.post(`/api/memories/${t.id}/open`,{action:e}).subscribe({next:()=>this.actionStatus.set(e==="open"?"Opened file":"Shown in folder"),error:()=>this.actionStatus.set("File actions require the local runtime")})}async copyPath(t){try{await globalThis.navigator?.clipboard?.writeText(t.sourcePath),this.actionStatus.set("Path copied")}catch{this.actionStatus.set("Could not copy the path")}}async copyContent(t){try{await globalThis.navigator?.clipboard?.writeText(t.content),this.actionStatus.set("Memory copied")}catch{this.actionStatus.set("Could not copy the memory")}}scopeLabel(t){return{global:"Global",repository:"Repository",session:"Session",workspace:"Workspace"}[t]}static \u0275fac=function(e){return new(e||a)};static \u0275cmp=I({type:a,selectors:[["app-memory-page"]],inputs:{memories:"memories",sessions:"sessions"},outputs:{openSession:"openSession"},decls:69,vars:17,consts:[[1,"memory-page"],[1,"memory-header"],[1,"eyebrow"],["aria-label","Memory summary",1,"memory-header-meta"],["aria-label","Memory filters",1,"memory-controls"],[1,"memory-search"],["type","search","placeholder","Search title, filename, content, or path",3,"ngModelChange","ngModel"],[3,"ngModelChange","ngModel"],["value","all"],["value","memory"],["value","plan"],["value","global"],["value","repository"],["value","session"],["value","workspace"],[3,"value"],[1,"memory-workspace"],[1,"memory-empty"],["aria-label","Saved memories",1,"memory-list"],[1,"memory-list-heading"],["type","button"],["type","button",1,"memory-card",3,"active","plan"],[1,"memory-detail"],["type","button",3,"click"],["type","button",1,"memory-card",3,"click"],["aria-hidden","true",1,"memory-file-icon"],[1,"memory-card-main"],[1,"memory-card-side"],[1,"memory-detail-header"],[1,"memory-kicker"],[1,"memory-actions"],[1,"memory-facts"],[1,"scope-fact"],["label","Explain memory scope",3,"text"],["aria-live","polite",1,"memory-action-status"],["aria-label","Observed memory use",1,"memory-recalls"],[1,"memory-source"],[1,"memory-content"],[1,"memory-path"],[1,"memory-recall-list"],[1,"memory-recall-row"],[1,"memory-recall-note"],[1,"memory-recall-facts"]],template:function(e,i){e&1&&(r(0,"section",0)(1,"header",1)(2,"div")(3,"p",2),o(4,"Copilot memory"),n(),r(5,"h2"),o(6,"What Copilot remembers"),n(),r(7,"p"),o(8,"Saved plans and memories from local VS Code Copilot storage."),n()(),r(9,"div",3)(10,"span")(11,"strong"),o(12),d(13,"number"),n(),o(14," files"),n(),r(15,"span")(16,"strong"),o(17),d(18,"number"),n(),o(19," plans"),n(),r(20,"span")(21,"strong"),o(22),d(23,"number"),n(),o(24," reads"),n(),r(25,"span")(26,"strong"),o(27),d(28,"number"),n(),o(29," workspaces"),n(),r(30,"b"),o(31,"Read-only"),n()()(),r(32,"section",4)(33,"label",5)(34,"span"),o(35,"Search memories"),n(),r(36,"input",6),_("ngModelChange",function(m){return i.setQuery(m)}),n()(),r(37,"label")(38,"span"),o(39,"Type"),n(),r(40,"select",7),_("ngModelChange",function(m){return i.setKindFilter(m)}),r(41,"option",8),o(42,"Memories and plans"),n(),r(43,"option",9),o(44,"Memories"),n(),r(45,"option",10),o(46,"Plans"),n()()(),r(47,"label")(48,"span"),o(49,"Scope"),n(),r(50,"select",7),_("ngModelChange",function(m){return i.setScopeFilter(m)}),r(51,"option",8),o(52,"All scopes"),n(),r(53,"option",11),o(54,"Global"),n(),r(55,"option",12),o(56,"Repository"),n(),r(57,"option",13),o(58,"Session"),n(),r(59,"option",14),o(60,"Workspace"),n()()(),r(61,"label")(62,"span"),o(63,"Workspace"),n(),r(64,"select",7),_("ngModelChange",function(m){return i.setWorkspaceFilter(m)}),O(65,Q,2,2,"option",15,F),n()()(),u(67,se,10,5,"section",16)(68,me,6,3,"section",17),n()),e&2&&(l(12),p(g(13,9,i.summary().total)),l(5),p(g(18,11,i.summary().plans)),l(5),p(g(23,13,i.summary().recalls)),l(5),p(g(28,15,i.summary().repositories)),l(9),f("ngModel",i.query()),l(4),f("ngModel",i.kindFilter()),l(10),f("ngModel",i.scopeFilter()),l(14),f("ngModel",i.workspaceFilter()),l(),S(i.workspaceOptions()),l(2),y(i.filteredMemories().length?67:68))},dependencies:[K,A,L,j,$,q,R,D,z,B],styles:['[_nghost-%COMP%]{display:block}.memory-page[_ngcontent-%COMP%]{display:grid;grid-template-rows:auto auto minmax(0,1fr);gap:8px;min-height:calc(100vh - 96px)}.memory-header[_ngcontent-%COMP%], .memory-controls[_ngcontent-%COMP%], .memory-list[_ngcontent-%COMP%], .memory-detail[_ngcontent-%COMP%], .memory-empty[_ngcontent-%COMP%]{border:1px solid var(--line);background:var(--surface);box-shadow:var(--shadow-soft)}.memory-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:14px;border-color:color-mix(in srgb,var(--accent-2) 18%,var(--line));border-radius:14px;padding:12px 14px;background:var(--header-gradient)}.eyebrow[_ngcontent-%COMP%], .memory-kicker[_ngcontent-%COMP%]{margin:0;color:var(--muted-2);font-size:9px;font-weight:820;letter-spacing:.08em;text-transform:uppercase}.memory-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], .memory-detail[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .memory-empty[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{margin:2px 0 0;color:var(--text-strong);letter-spacing:0}.memory-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{font-size:21px;line-height:1.15}.memory-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .memory-detail-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .memory-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:4px 0 0;color:var(--muted);font-size:12px;line-height:1.35}.memory-header-meta[_ngcontent-%COMP%]{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:5px}.memory-header-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .memory-header-meta[_ngcontent-%COMP%] b[_ngcontent-%COMP%]{display:inline-flex;align-items:center;min-height:24px;border:1px solid var(--line);border-radius:999px;padding:3px 8px;background:color-mix(in srgb,var(--surface) 74%,transparent);color:var(--muted);font-size:11px;font-weight:720;white-space:nowrap}.memory-header-meta[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{margin-right:4px;color:var(--text-strong)}.memory-header-meta[_ngcontent-%COMP%] b[_ngcontent-%COMP%]{border-color:color-mix(in srgb,var(--accent) 28%,var(--line));color:var(--accent)}.memory-controls[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(260px,1.8fr) repeat(3,minmax(130px,.8fr));gap:7px;border-radius:12px;padding:8px}.memory-controls[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{display:grid;gap:4px}.memory-controls[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:var(--muted);font-size:10px;font-weight:760}.memory-controls[_ngcontent-%COMP%] input[_ngcontent-%COMP%], .memory-controls[_ngcontent-%COMP%] select[_ngcontent-%COMP%]{width:100%;min-height:32px;border:1px solid var(--line);border-radius:8px;padding:6px 9px;background:var(--surface-soft);color:var(--text);font:inherit;font-size:12px}.memory-workspace[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(320px,380px) minmax(0,1fr);gap:10px;align-items:start;min-height:0}.memory-list[_ngcontent-%COMP%], .memory-detail[_ngcontent-%COMP%], .memory-empty[_ngcontent-%COMP%]{border-radius:13px}.memory-list[_ngcontent-%COMP%]{position:sticky;top:70px;display:grid;align-content:start;gap:3px;max-height:calc(100vh - 150px);overflow:auto;padding:7px}.memory-list-heading[_ngcontent-%COMP%]{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;min-height:28px;padding:2px 4px 5px;background:var(--surface);color:var(--muted);font-size:11px}.memory-list-heading[_ngcontent-%COMP%] button[_ngcontent-%COMP%], .memory-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%], .memory-facts[_ngcontent-%COMP%] button[_ngcontent-%COMP%], .memory-empty[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{border:1px solid var(--line);border-radius:7px;padding:5px 8px;background:var(--surface-soft);color:var(--text);font:inherit;font-size:11px;font-weight:760;cursor:pointer}.memory-card[_ngcontent-%COMP%]{display:grid;grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:8px;width:100%;min-height:47px;border:1px solid transparent;border-radius:8px;padding:7px 8px;background:transparent;color:var(--text);text-align:left;cursor:pointer}.memory-card[_ngcontent-%COMP%]:hover, .memory-card.active[_ngcontent-%COMP%]{border-color:color-mix(in srgb,var(--accent) 34%,var(--line));background:color-mix(in srgb,var(--accent) 6%,var(--surface-soft))}.memory-card.plan.active[_ngcontent-%COMP%]{border-color:color-mix(in srgb,var(--accent-2) 42%,var(--line));background:color-mix(in srgb,var(--accent-2) 7%,var(--surface-soft))}.memory-file-icon[_ngcontent-%COMP%]{display:grid;place-items:center;width:22px;height:22px;border-radius:6px;background:color-mix(in srgb,var(--accent) 12%,var(--surface-soft));color:var(--accent);font-size:10px;font-weight:850}.memory-card.plan[_ngcontent-%COMP%] .memory-file-icon[_ngcontent-%COMP%]{background:color-mix(in srgb,var(--accent-2) 14%,var(--surface-soft));color:var(--accent-2)}.memory-card-main[_ngcontent-%COMP%], .memory-card-side[_ngcontent-%COMP%]{display:grid;gap:2px;min-width:0}.memory-card-main[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{overflow:hidden;color:var(--text-strong);font-size:13px;font-weight:760;line-height:1.22;text-overflow:ellipsis;white-space:nowrap}.memory-card-main[_ngcontent-%COMP%] small[_ngcontent-%COMP%]{overflow:hidden;color:var(--muted-2);font-size:10px;line-height:1.15;text-overflow:ellipsis;white-space:nowrap}.memory-card-side[_ngcontent-%COMP%]{justify-items:end;color:var(--muted-2);font-size:10px;white-space:nowrap}.memory-card-side[_ngcontent-%COMP%] b[_ngcontent-%COMP%]{color:var(--muted);font-size:10px;text-transform:uppercase}.memory-card-side[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{border-radius:999px;padding:2px 6px;background:color-mix(in srgb,var(--accent) 10%,var(--surface));color:var(--accent);font-style:normal;font-weight:760}.memory-detail[_ngcontent-%COMP%]{min-width:0;padding:14px}.memory-detail-header[_ngcontent-%COMP%]{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.memory-detail[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{font-size:20px;line-height:1.2}.memory-actions[_ngcontent-%COMP%], .memory-facts[_ngcontent-%COMP%]{display:flex;flex-wrap:wrap;gap:6px}.memory-actions[_ngcontent-%COMP%]{justify-content:flex-end}.memory-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:first-child{border-color:var(--accent);background:var(--accent);color:#fff}.memory-facts[_ngcontent-%COMP%]{margin-top:10px}.memory-facts[_ngcontent-%COMP%] > span[_ngcontent-%COMP%], .memory-facts[_ngcontent-%COMP%] > button[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;min-height:25px;border:1px solid var(--line);border-radius:999px;padding:4px 8px;background:var(--surface-soft);color:var(--muted);font-size:11px}.memory-facts[_ngcontent-%COMP%] b[_ngcontent-%COMP%]{color:var(--text-strong)}.memory-facts[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{color:var(--accent)}.memory-action-status[_ngcontent-%COMP%]{margin:9px 0 0;color:var(--accent);font-size:11px}.memory-recalls[_ngcontent-%COMP%]{display:grid;gap:8px;margin-top:12px;border:1px solid color-mix(in srgb,var(--accent) 22%,var(--line));border-radius:10px;padding:10px;background:color-mix(in srgb,var(--accent) 4%,var(--surface-soft))}.memory-recalls[_ngcontent-%COMP%] > header[_ngcontent-%COMP%]{display:flex;align-items:end;justify-content:space-between;gap:10px}.memory-recalls[_ngcontent-%COMP%] h4[_ngcontent-%COMP%]{margin:2px 0 0;color:var(--text-strong);font-size:14px}.memory-recalls[_ngcontent-%COMP%] > header[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .memory-recall-note[_ngcontent-%COMP%]{margin:0;color:var(--muted);font-size:11px}.memory-recall-list[_ngcontent-%COMP%]{display:grid;gap:5px}.memory-recall-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(180px,.8fr) minmax(230px,1.2fr);gap:10px;border-top:1px solid var(--line);padding-top:7px}.memory-recall-row[_ngcontent-%COMP%] > div[_ngcontent-%COMP%], .memory-recall-facts[_ngcontent-%COMP%]{display:grid;gap:2px}.memory-recall-row[_ngcontent-%COMP%] time[_ngcontent-%COMP%], .memory-recall-row[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:var(--muted);font-size:11px}.memory-recall-row[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{width:fit-content;border:0;padding:0;background:none;color:var(--accent);font:inherit;font-size:12px;font-weight:760;text-align:left;cursor:pointer}.memory-source[_ngcontent-%COMP%]{margin-top:12px;border:1px solid var(--line);border-radius:10px;background:var(--surface-soft)}.memory-source[_ngcontent-%COMP%] summary[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:38px;padding:8px 11px;color:var(--text-strong);cursor:pointer;list-style:none}.memory-source[_ngcontent-%COMP%] summary[_ngcontent-%COMP%]::-webkit-details-marker{display:none}.memory-source[_ngcontent-%COMP%] summary[_ngcontent-%COMP%]:before{content:"";flex:0 0 auto;width:7px;height:7px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(-45deg);transition:transform .14s ease}.memory-source[open][_ngcontent-%COMP%] summary[_ngcontent-%COMP%]:before{transform:rotate(45deg)}.memory-source[_ngcontent-%COMP%] summary[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{flex:1;font-size:12px;font-weight:780}.memory-source[_ngcontent-%COMP%] summary[_ngcontent-%COMP%] small[_ngcontent-%COMP%]{color:var(--muted);font-size:11px}.memory-content[_ngcontent-%COMP%]{max-height:48vh;margin:0;border-top:1px solid var(--line);padding:14px;overflow:auto;color:var(--text);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px;line-height:1.58;white-space:pre-wrap;overflow-wrap:anywhere}.memory-path[_ngcontent-%COMP%]{display:grid;gap:4px;margin-top:10px;color:var(--muted-2);font-size:10px;text-transform:uppercase}.memory-path[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{color:var(--muted);font-size:11px;text-transform:none;overflow-wrap:anywhere}.memory-empty[_ngcontent-%COMP%]{display:grid;justify-items:start;padding:28px}@media(max-width:1050px){.memory-controls[_ngcontent-%COMP%]{grid-template-columns:repeat(2,minmax(0,1fr))}.memory-search[_ngcontent-%COMP%]{grid-column:1 / -1}}@media(max-width:820px){.memory-page[_ngcontent-%COMP%]{min-height:auto}.memory-detail-header[_ngcontent-%COMP%]{display:grid}.memory-workspace[_ngcontent-%COMP%]{grid-template-columns:1fr}.memory-header[_ngcontent-%COMP%]{align-items:flex-start;padding:10px}.memory-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{display:none}.memory-header-meta[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(2,max-content);justify-content:end;gap:4px}.memory-header-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .memory-header-meta[_ngcontent-%COMP%] b[_ngcontent-%COMP%]{min-height:21px;padding:2px 6px;font-size:10px}.memory-controls[_ngcontent-%COMP%]{grid-template-columns:repeat(3,minmax(0,1fr))}.memory-search[_ngcontent-%COMP%]{grid-column:1 / -1}.memory-list[_ngcontent-%COMP%]{position:static;max-height:420px}.memory-actions[_ngcontent-%COMP%]{justify-content:flex-start}.memory-recalls[_ngcontent-%COMP%] > header[_ngcontent-%COMP%], .memory-recall-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr}}@media(max-width:480px){.memory-header[_ngcontent-%COMP%]{display:grid}.memory-header-meta[_ngcontent-%COMP%]{justify-content:start}.memory-controls[_ngcontent-%COMP%] input[_ngcontent-%COMP%], .memory-controls[_ngcontent-%COMP%] select[_ngcontent-%COMP%]{padding-inline:6px;font-size:11px}.memory-controls[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{font-size:9px}}']})};export{W as MemoryPageComponent};