@a4hgehad/weave-mcp 0.8.0 → 0.8.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 (2) hide show
  1. package/dist/index.js +262 -237
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -98,11 +98,12 @@ var BuiltInMcpSchema = z.object({
98
98
  grep_app: z.boolean().optional()
99
99
  });
100
100
  var CustomMcpServerSchema = z.object({
101
- type: z.enum(["stdio", "http"]).optional(),
102
- command: z.string().optional(),
101
+ type: z.enum(["local", "remote"]).optional(),
102
+ command: z.array(z.string()).optional(),
103
103
  args: z.array(z.string()).optional(),
104
104
  url: z.string().optional(),
105
- env: z.record(z.string(), z.string()).optional()
105
+ env: z.record(z.string(), z.string()).optional(),
106
+ enabled: z.boolean().optional()
106
107
  });
107
108
  var McpConfigSchema = z.object({
108
109
  enabled: BuiltInMcpSchema.optional(),
@@ -241,19 +242,16 @@ function loadWeaveConfig(directory, _ctx, _homeDir) {
241
242
  // src/mcp/types.ts
242
243
  var BUILTIN_MCP_SERVERS = {
243
244
  websearch: {
244
- type: "stdio",
245
- command: "npx",
246
- args: ["-y", "@modelcontextprotocol/server-websearch"]
245
+ type: "local",
246
+ command: ["npx", "-y", "@modelcontextprotocol/server-websearch"]
247
247
  },
248
248
  context7: {
249
- type: "stdio",
250
- command: "npx",
251
- args: ["-y", "context7-mcp-server"]
249
+ type: "local",
250
+ command: ["npx", "-y", "context7-mcp-server"]
252
251
  },
253
252
  grep_app: {
254
- type: "stdio",
255
- command: "npx",
256
- args: ["-y", "grep-app-mcp"]
253
+ type: "local",
254
+ command: ["npx", "-y", "grep-app-mcp"]
257
255
  }
258
256
  };
259
257
  var DEFAULT_MCPS = ["websearch", "context7", "grep_app"];
@@ -4634,221 +4632,6 @@ function getState(sessionId) {
4634
4632
  function clearSession2(sessionId) {
4635
4633
  sessionMap.delete(sessionId);
4636
4634
  }
4637
- // src/features/analytics/storage.ts
4638
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, appendFileSync as appendFileSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync4, statSync as statSync3 } from "fs";
4639
- import { join as join11 } from "path";
4640
-
4641
- // src/features/analytics/types.ts
4642
- var ANALYTICS_DIR = ".weave/analytics";
4643
- var SESSION_SUMMARIES_FILE = "session-summaries.jsonl";
4644
- var FINGERPRINT_FILE = "fingerprint.json";
4645
- var METRICS_REPORTS_FILE = "metrics-reports.jsonl";
4646
- var MAX_METRICS_ENTRIES = 100;
4647
- function zeroTokenUsage() {
4648
- return { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0 };
4649
- }
4650
-
4651
- // src/features/analytics/storage.ts
4652
- var MAX_SESSION_ENTRIES = 1000;
4653
- function ensureAnalyticsDir(directory) {
4654
- const dir = join11(directory, ANALYTICS_DIR);
4655
- mkdirSync5(dir, { recursive: true, mode: 448 });
4656
- return dir;
4657
- }
4658
- function appendSessionSummary(directory, summary) {
4659
- try {
4660
- const dir = ensureAnalyticsDir(directory);
4661
- const filePath = join11(dir, SESSION_SUMMARIES_FILE);
4662
- const line = JSON.stringify(summary) + `
4663
- `;
4664
- appendFileSync2(filePath, line, { encoding: "utf-8", mode: 384 });
4665
- try {
4666
- const TYPICAL_ENTRY_BYTES = 200;
4667
- const rotationSizeThreshold = MAX_SESSION_ENTRIES * TYPICAL_ENTRY_BYTES * 0.9;
4668
- const { size } = statSync3(filePath);
4669
- if (size > rotationSizeThreshold) {
4670
- const content = readFileSync10(filePath, "utf-8");
4671
- const lines = content.split(`
4672
- `).filter((l) => l.trim().length > 0);
4673
- if (lines.length > MAX_SESSION_ENTRIES) {
4674
- const trimmed = lines.slice(-MAX_SESSION_ENTRIES).join(`
4675
- `) + `
4676
- `;
4677
- writeFileSync4(filePath, trimmed, { encoding: "utf-8", mode: 384 });
4678
- }
4679
- }
4680
- } catch {}
4681
- return true;
4682
- } catch {
4683
- return false;
4684
- }
4685
- }
4686
- function readSessionSummaries(directory) {
4687
- const filePath = join11(directory, ANALYTICS_DIR, SESSION_SUMMARIES_FILE);
4688
- try {
4689
- if (!existsSync12(filePath))
4690
- return [];
4691
- const content = readFileSync10(filePath, "utf-8");
4692
- const lines = content.split(`
4693
- `).filter((line) => line.trim().length > 0);
4694
- const summaries = [];
4695
- for (const line of lines) {
4696
- try {
4697
- summaries.push(JSON.parse(line));
4698
- } catch {}
4699
- }
4700
- return summaries;
4701
- } catch {
4702
- return [];
4703
- }
4704
- }
4705
- function writeFingerprint(directory, fingerprint) {
4706
- try {
4707
- const dir = ensureAnalyticsDir(directory);
4708
- const filePath = join11(dir, FINGERPRINT_FILE);
4709
- writeFileSync4(filePath, JSON.stringify(fingerprint, null, 2), { encoding: "utf-8", mode: 384 });
4710
- return true;
4711
- } catch {
4712
- return false;
4713
- }
4714
- }
4715
- function readFingerprint(directory) {
4716
- const filePath = join11(directory, ANALYTICS_DIR, FINGERPRINT_FILE);
4717
- try {
4718
- if (!existsSync12(filePath))
4719
- return null;
4720
- const content = readFileSync10(filePath, "utf-8");
4721
- const parsed = JSON.parse(content);
4722
- if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.stack))
4723
- return null;
4724
- return parsed;
4725
- } catch {
4726
- return null;
4727
- }
4728
- }
4729
- function writeMetricsReport(directory, report) {
4730
- try {
4731
- const dir = ensureAnalyticsDir(directory);
4732
- const filePath = join11(dir, METRICS_REPORTS_FILE);
4733
- const line = JSON.stringify(report) + `
4734
- `;
4735
- appendFileSync2(filePath, line, { encoding: "utf-8", mode: 384 });
4736
- try {
4737
- const TYPICAL_ENTRY_BYTES = 200;
4738
- const rotationSizeThreshold = MAX_METRICS_ENTRIES * TYPICAL_ENTRY_BYTES * 0.9;
4739
- const { size } = statSync3(filePath);
4740
- if (size > rotationSizeThreshold) {
4741
- const content = readFileSync10(filePath, "utf-8");
4742
- const lines = content.split(`
4743
- `).filter((l) => l.trim().length > 0);
4744
- if (lines.length > MAX_METRICS_ENTRIES) {
4745
- const trimmed = lines.slice(-MAX_METRICS_ENTRIES).join(`
4746
- `) + `
4747
- `;
4748
- writeFileSync4(filePath, trimmed, { encoding: "utf-8", mode: 384 });
4749
- }
4750
- }
4751
- } catch {}
4752
- return true;
4753
- } catch {
4754
- return false;
4755
- }
4756
- }
4757
- function readMetricsReports(directory) {
4758
- const filePath = join11(directory, ANALYTICS_DIR, METRICS_REPORTS_FILE);
4759
- try {
4760
- if (!existsSync12(filePath))
4761
- return [];
4762
- const content = readFileSync10(filePath, "utf-8");
4763
- const lines = content.split(`
4764
- `).filter((line) => line.trim().length > 0);
4765
- const reports = [];
4766
- for (const line of lines) {
4767
- try {
4768
- reports.push(JSON.parse(line));
4769
- } catch {}
4770
- }
4771
- return reports;
4772
- } catch {
4773
- return [];
4774
- }
4775
- }
4776
-
4777
- // src/features/analytics/token-report.ts
4778
- function generateTokenReport(summaries) {
4779
- if (summaries.length === 0) {
4780
- return "No session data available.";
4781
- }
4782
- const sections = [];
4783
- const totalSessions = summaries.length;
4784
- const totalMessages = summaries.reduce((sum, s) => sum + (s.tokenUsage?.totalMessages ?? 0), 0);
4785
- const totalInput = summaries.reduce((sum, s) => sum + (s.tokenUsage?.inputTokens ?? 0), 0);
4786
- const totalOutput = summaries.reduce((sum, s) => sum + (s.tokenUsage?.outputTokens ?? 0), 0);
4787
- const totalReasoning = summaries.reduce((sum, s) => sum + (s.tokenUsage?.reasoningTokens ?? 0), 0);
4788
- const totalCacheRead = summaries.reduce((sum, s) => sum + (s.tokenUsage?.cacheReadTokens ?? 0), 0);
4789
- const totalCacheWrite = summaries.reduce((sum, s) => sum + (s.tokenUsage?.cacheWriteTokens ?? 0), 0);
4790
- const totalCost = summaries.reduce((sum, s) => sum + (s.totalCost ?? 0), 0);
4791
- sections.push(`## Overall Totals
4792
- ` + `- Sessions: ${fmt(totalSessions)}
4793
- ` + `- Messages: ${fmt(totalMessages)}
4794
- ` + `- Input tokens: ${fmt(totalInput)}
4795
- ` + `- Output tokens: ${fmt(totalOutput)}
4796
- ` + `- Reasoning tokens: ${fmt(totalReasoning)}
4797
- ` + `- Cache read tokens: ${fmt(totalCacheRead)}
4798
- ` + `- Cache write tokens: ${fmt(totalCacheWrite)}
4799
- ` + `- Total cost: ${fmtCost(totalCost)}`);
4800
- const agentGroups = new Map;
4801
- for (const s of summaries) {
4802
- const key = s.agentName ?? "(unknown)";
4803
- const group = agentGroups.get(key);
4804
- if (group) {
4805
- group.push(s);
4806
- } else {
4807
- agentGroups.set(key, [s]);
4808
- }
4809
- }
4810
- const agentStats = Array.from(agentGroups.entries()).map(([agent, sessions]) => {
4811
- const agentCost = sessions.reduce((sum, s) => sum + (s.totalCost ?? 0), 0);
4812
- const agentTokens = sessions.reduce((sum, s) => sum + (s.tokenUsage?.inputTokens ?? 0) + (s.tokenUsage?.outputTokens ?? 0) + (s.tokenUsage?.reasoningTokens ?? 0), 0);
4813
- const avgTokens = sessions.length > 0 ? Math.round(agentTokens / sessions.length) : 0;
4814
- const avgCost = sessions.length > 0 ? agentCost / sessions.length : 0;
4815
- return { agent, sessions: sessions.length, avgTokens, avgCost, totalCost: agentCost };
4816
- }).sort((a, b) => b.totalCost - a.totalCost);
4817
- const agentLines = agentStats.map((a) => `- **${a.agent}**: ${fmt(a.sessions)} session${a.sessions === 1 ? "" : "s"}, ` + `avg ${fmt(a.avgTokens)} tokens/session, ` + `avg ${fmtCost(a.avgCost)}/session, ` + `total ${fmtCost(a.totalCost)}`);
4818
- sections.push(`## Per-Agent Breakdown
4819
- ${agentLines.join(`
4820
- `)}`);
4821
- const top5 = [...summaries].sort((a, b) => (b.totalCost ?? 0) - (a.totalCost ?? 0)).slice(0, 5);
4822
- const top5Lines = top5.map((s) => {
4823
- const id = s.sessionId.length > 8 ? s.sessionId.slice(0, 8) : s.sessionId;
4824
- const agent = s.agentName ?? "(unknown)";
4825
- const cost = fmtCost(s.totalCost ?? 0);
4826
- const tokens = (s.tokenUsage?.inputTokens ?? 0) + (s.tokenUsage?.outputTokens ?? 0) + (s.tokenUsage?.reasoningTokens ?? 0);
4827
- const duration = fmtDuration(s.durationMs);
4828
- return `- \`${id}\` ${agent} — ${cost}, ${fmt(tokens)} tokens, ${duration}`;
4829
- });
4830
- sections.push(`## Top 5 Costliest Sessions
4831
- ${top5Lines.join(`
4832
- `)}`);
4833
- return sections.join(`
4834
-
4835
- `);
4836
- }
4837
- function fmt(n) {
4838
- return n.toLocaleString("en-US");
4839
- }
4840
- function fmtCost(n) {
4841
- return `$${n.toFixed(2)}`;
4842
- }
4843
- function fmtDuration(ms) {
4844
- const totalSeconds = Math.round(ms / 1000);
4845
- const minutes = Math.floor(totalSeconds / 60);
4846
- const seconds = totalSeconds % 60;
4847
- if (minutes === 0)
4848
- return `${seconds}s`;
4849
- return `${minutes}m ${seconds}s`;
4850
- }
4851
-
4852
4635
  // src/features/analytics/format-metrics.ts
4853
4636
  function formatNumber(n) {
4854
4637
  return n.toLocaleString("en-US");
@@ -4985,7 +4768,7 @@ function formatMetricsMarkdown(reports, summaries, args) {
4985
4768
  }
4986
4769
 
4987
4770
  // src/features/analytics/plan-parser.ts
4988
- import { readFileSync as readFileSync11 } from "fs";
4771
+ import { readFileSync as readFileSync10 } from "fs";
4989
4772
  function extractSection2(content, heading) {
4990
4773
  const lines = content.split(`
4991
4774
  `);
@@ -5020,7 +4803,7 @@ function extractFilePath2(raw) {
5020
4803
  function extractPlannedFiles(planPath) {
5021
4804
  let content;
5022
4805
  try {
5023
- content = readFileSync11(planPath, "utf-8");
4806
+ content = readFileSync10(planPath, "utf-8");
5024
4807
  } catch {
5025
4808
  return [];
5026
4809
  }
@@ -5107,6 +4890,144 @@ function calculateAdherence(plannedFiles, actualFiles) {
5107
4890
  };
5108
4891
  }
5109
4892
 
4893
+ // src/features/analytics/types.ts
4894
+ var ANALYTICS_DIR = ".weave/analytics";
4895
+ var SESSION_SUMMARIES_FILE = "session-summaries.jsonl";
4896
+ var FINGERPRINT_FILE = "fingerprint.json";
4897
+ var METRICS_REPORTS_FILE = "metrics-reports.jsonl";
4898
+ var MAX_METRICS_ENTRIES = 100;
4899
+ function zeroTokenUsage() {
4900
+ return { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0 };
4901
+ }
4902
+
4903
+ // src/features/analytics/storage.ts
4904
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, appendFileSync as appendFileSync2, readFileSync as readFileSync11, writeFileSync as writeFileSync4, statSync as statSync3 } from "fs";
4905
+ import { join as join11 } from "path";
4906
+ var MAX_SESSION_ENTRIES = 1000;
4907
+ function ensureAnalyticsDir(directory) {
4908
+ const dir = join11(directory, ANALYTICS_DIR);
4909
+ mkdirSync5(dir, { recursive: true, mode: 448 });
4910
+ return dir;
4911
+ }
4912
+ function appendSessionSummary(directory, summary) {
4913
+ try {
4914
+ const dir = ensureAnalyticsDir(directory);
4915
+ const filePath = join11(dir, SESSION_SUMMARIES_FILE);
4916
+ const line = JSON.stringify(summary) + `
4917
+ `;
4918
+ appendFileSync2(filePath, line, { encoding: "utf-8", mode: 384 });
4919
+ try {
4920
+ const TYPICAL_ENTRY_BYTES = 200;
4921
+ const rotationSizeThreshold = MAX_SESSION_ENTRIES * TYPICAL_ENTRY_BYTES * 0.9;
4922
+ const { size } = statSync3(filePath);
4923
+ if (size > rotationSizeThreshold) {
4924
+ const content = readFileSync11(filePath, "utf-8");
4925
+ const lines = content.split(`
4926
+ `).filter((l) => l.trim().length > 0);
4927
+ if (lines.length > MAX_SESSION_ENTRIES) {
4928
+ const trimmed = lines.slice(-MAX_SESSION_ENTRIES).join(`
4929
+ `) + `
4930
+ `;
4931
+ writeFileSync4(filePath, trimmed, { encoding: "utf-8", mode: 384 });
4932
+ }
4933
+ }
4934
+ } catch {}
4935
+ return true;
4936
+ } catch {
4937
+ return false;
4938
+ }
4939
+ }
4940
+ function readSessionSummaries(directory) {
4941
+ const filePath = join11(directory, ANALYTICS_DIR, SESSION_SUMMARIES_FILE);
4942
+ try {
4943
+ if (!existsSync12(filePath))
4944
+ return [];
4945
+ const content = readFileSync11(filePath, "utf-8");
4946
+ const lines = content.split(`
4947
+ `).filter((line) => line.trim().length > 0);
4948
+ const summaries = [];
4949
+ for (const line of lines) {
4950
+ try {
4951
+ summaries.push(JSON.parse(line));
4952
+ } catch {}
4953
+ }
4954
+ return summaries;
4955
+ } catch {
4956
+ return [];
4957
+ }
4958
+ }
4959
+ function writeFingerprint(directory, fingerprint) {
4960
+ try {
4961
+ const dir = ensureAnalyticsDir(directory);
4962
+ const filePath = join11(dir, FINGERPRINT_FILE);
4963
+ writeFileSync4(filePath, JSON.stringify(fingerprint, null, 2), { encoding: "utf-8", mode: 384 });
4964
+ return true;
4965
+ } catch {
4966
+ return false;
4967
+ }
4968
+ }
4969
+ function readFingerprint(directory) {
4970
+ const filePath = join11(directory, ANALYTICS_DIR, FINGERPRINT_FILE);
4971
+ try {
4972
+ if (!existsSync12(filePath))
4973
+ return null;
4974
+ const content = readFileSync11(filePath, "utf-8");
4975
+ const parsed = JSON.parse(content);
4976
+ if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.stack))
4977
+ return null;
4978
+ return parsed;
4979
+ } catch {
4980
+ return null;
4981
+ }
4982
+ }
4983
+ function writeMetricsReport(directory, report) {
4984
+ try {
4985
+ const dir = ensureAnalyticsDir(directory);
4986
+ const filePath = join11(dir, METRICS_REPORTS_FILE);
4987
+ const line = JSON.stringify(report) + `
4988
+ `;
4989
+ appendFileSync2(filePath, line, { encoding: "utf-8", mode: 384 });
4990
+ try {
4991
+ const TYPICAL_ENTRY_BYTES = 200;
4992
+ const rotationSizeThreshold = MAX_METRICS_ENTRIES * TYPICAL_ENTRY_BYTES * 0.9;
4993
+ const { size } = statSync3(filePath);
4994
+ if (size > rotationSizeThreshold) {
4995
+ const content = readFileSync11(filePath, "utf-8");
4996
+ const lines = content.split(`
4997
+ `).filter((l) => l.trim().length > 0);
4998
+ if (lines.length > MAX_METRICS_ENTRIES) {
4999
+ const trimmed = lines.slice(-MAX_METRICS_ENTRIES).join(`
5000
+ `) + `
5001
+ `;
5002
+ writeFileSync4(filePath, trimmed, { encoding: "utf-8", mode: 384 });
5003
+ }
5004
+ }
5005
+ } catch {}
5006
+ return true;
5007
+ } catch {
5008
+ return false;
5009
+ }
5010
+ }
5011
+ function readMetricsReports(directory) {
5012
+ const filePath = join11(directory, ANALYTICS_DIR, METRICS_REPORTS_FILE);
5013
+ try {
5014
+ if (!existsSync12(filePath))
5015
+ return [];
5016
+ const content = readFileSync11(filePath, "utf-8");
5017
+ const lines = content.split(`
5018
+ `).filter((line) => line.trim().length > 0);
5019
+ const reports = [];
5020
+ for (const line of lines) {
5021
+ try {
5022
+ reports.push(JSON.parse(line));
5023
+ } catch {}
5024
+ }
5025
+ return reports;
5026
+ } catch {
5027
+ return [];
5028
+ }
5029
+ }
5030
+
5110
5031
  // src/features/analytics/plan-token-aggregator.ts
5111
5032
  function aggregateTokensForPlan(directory, sessionIds) {
5112
5033
  const summaries = readSessionSummaries(directory);
@@ -5167,10 +5088,95 @@ function generateMetricsReport(directory, state) {
5167
5088
  }
5168
5089
  }
5169
5090
 
5091
+ // src/features/analytics/token-report.ts
5092
+ function generateTokenReport(summaries) {
5093
+ if (summaries.length === 0) {
5094
+ return "No session data available.";
5095
+ }
5096
+ const sections = [];
5097
+ const totalSessions = summaries.length;
5098
+ const totalMessages = summaries.reduce((sum, s) => sum + (s.tokenUsage?.totalMessages ?? 0), 0);
5099
+ const totalInput = summaries.reduce((sum, s) => sum + (s.tokenUsage?.inputTokens ?? 0), 0);
5100
+ const totalOutput = summaries.reduce((sum, s) => sum + (s.tokenUsage?.outputTokens ?? 0), 0);
5101
+ const totalReasoning = summaries.reduce((sum, s) => sum + (s.tokenUsage?.reasoningTokens ?? 0), 0);
5102
+ const totalCacheRead = summaries.reduce((sum, s) => sum + (s.tokenUsage?.cacheReadTokens ?? 0), 0);
5103
+ const totalCacheWrite = summaries.reduce((sum, s) => sum + (s.tokenUsage?.cacheWriteTokens ?? 0), 0);
5104
+ const totalCost = summaries.reduce((sum, s) => sum + (s.totalCost ?? 0), 0);
5105
+ sections.push(`## Overall Totals
5106
+ ` + `- Sessions: ${fmt(totalSessions)}
5107
+ ` + `- Messages: ${fmt(totalMessages)}
5108
+ ` + `- Input tokens: ${fmt(totalInput)}
5109
+ ` + `- Output tokens: ${fmt(totalOutput)}
5110
+ ` + `- Reasoning tokens: ${fmt(totalReasoning)}
5111
+ ` + `- Cache read tokens: ${fmt(totalCacheRead)}
5112
+ ` + `- Cache write tokens: ${fmt(totalCacheWrite)}
5113
+ ` + `- Total cost: ${fmtCost(totalCost)}`);
5114
+ const agentGroups = new Map;
5115
+ for (const s of summaries) {
5116
+ const key = s.agentName ?? "(unknown)";
5117
+ const group = agentGroups.get(key);
5118
+ if (group) {
5119
+ group.push(s);
5120
+ } else {
5121
+ agentGroups.set(key, [s]);
5122
+ }
5123
+ }
5124
+ const agentStats = Array.from(agentGroups.entries()).map(([agent, sessions]) => {
5125
+ const agentCost = sessions.reduce((sum, s) => sum + (s.totalCost ?? 0), 0);
5126
+ const agentTokens = sessions.reduce((sum, s) => sum + (s.tokenUsage?.inputTokens ?? 0) + (s.tokenUsage?.outputTokens ?? 0) + (s.tokenUsage?.reasoningTokens ?? 0), 0);
5127
+ const avgTokens = sessions.length > 0 ? Math.round(agentTokens / sessions.length) : 0;
5128
+ const avgCost = sessions.length > 0 ? agentCost / sessions.length : 0;
5129
+ return { agent, sessions: sessions.length, avgTokens, avgCost, totalCost: agentCost };
5130
+ }).sort((a, b) => b.totalCost - a.totalCost);
5131
+ const agentLines = agentStats.map((a) => `- **${a.agent}**: ${fmt(a.sessions)} session${a.sessions === 1 ? "" : "s"}, ` + `avg ${fmt(a.avgTokens)} tokens/session, ` + `avg ${fmtCost(a.avgCost)}/session, ` + `total ${fmtCost(a.totalCost)}`);
5132
+ sections.push(`## Per-Agent Breakdown
5133
+ ${agentLines.join(`
5134
+ `)}`);
5135
+ const top5 = [...summaries].sort((a, b) => (b.totalCost ?? 0) - (a.totalCost ?? 0)).slice(0, 5);
5136
+ const top5Lines = top5.map((s) => {
5137
+ const id = s.sessionId.length > 8 ? s.sessionId.slice(0, 8) : s.sessionId;
5138
+ const agent = s.agentName ?? "(unknown)";
5139
+ const cost = fmtCost(s.totalCost ?? 0);
5140
+ const tokens = (s.tokenUsage?.inputTokens ?? 0) + (s.tokenUsage?.outputTokens ?? 0) + (s.tokenUsage?.reasoningTokens ?? 0);
5141
+ const duration = fmtDuration(s.durationMs);
5142
+ return `- \`${id}\` ${agent} — ${cost}, ${fmt(tokens)} tokens, ${duration}`;
5143
+ });
5144
+ sections.push(`## Top 5 Costliest Sessions
5145
+ ${top5Lines.join(`
5146
+ `)}`);
5147
+ return sections.join(`
5148
+
5149
+ `);
5150
+ }
5151
+ function fmt(n) {
5152
+ return n.toLocaleString("en-US");
5153
+ }
5154
+ function fmtCost(n) {
5155
+ return `$${n.toFixed(2)}`;
5156
+ }
5157
+ function fmtDuration(ms) {
5158
+ const totalSeconds = Math.round(ms / 1000);
5159
+ const minutes = Math.floor(totalSeconds / 60);
5160
+ const seconds = totalSeconds % 60;
5161
+ if (minutes === 0)
5162
+ return `${seconds}s`;
5163
+ return `${minutes}m ${seconds}s`;
5164
+ }
5165
+
5170
5166
  // src/plugin/plugin-interface.ts
5171
5167
  var FINALIZE_TODOS_MARKER = "<!-- weave:finalize-todos -->";
5172
5168
  function createPluginInterface(args) {
5173
- const { pluginConfig, hooks, tools, configHandler, agents, client, directory = "", tracker, taskSystemEnabled = false } = args;
5169
+ const {
5170
+ pluginConfig,
5171
+ hooks,
5172
+ tools,
5173
+ configHandler,
5174
+ agents,
5175
+ client,
5176
+ directory = "",
5177
+ tracker,
5178
+ taskSystemEnabled = false
5179
+ } = args;
5174
5180
  const lastAssistantMessageText = new Map;
5175
5181
  const lastUserMessageText = new Map;
5176
5182
  const todoFinalizedSessions = new Set;
@@ -5184,6 +5190,7 @@ function createPluginInterface(args) {
5184
5190
  });
5185
5191
  config.agent = result.agents;
5186
5192
  config.command = result.commands;
5193
+ config.mcps = result.mcps;
5187
5194
  if (result.defaultAgent) {
5188
5195
  config.default_agent = result.defaultAgent;
5189
5196
  }
@@ -5313,7 +5320,10 @@ ${cmdResult.contextInjection}`;
5313
5320
  const maxTokens = input.model?.limit?.context ?? 0;
5314
5321
  if (sessionId && maxTokens > 0) {
5315
5322
  setContextLimit(sessionId, maxTokens);
5316
- log("[context-window] Captured context limit", { sessionId, maxTokens });
5323
+ log("[context-window] Captured context limit", {
5324
+ sessionId,
5325
+ maxTokens
5326
+ });
5317
5327
  }
5318
5328
  if (tracker && hooks.analyticsEnabled && sessionId && input.agent) {
5319
5329
  tracker.setAgentName(sessionId, input.agent);
@@ -5340,7 +5350,9 @@ ${cmdResult.contextInjection}`;
5340
5350
  try {
5341
5351
  tracker.endSession(evt.properties.info.id);
5342
5352
  } catch (err) {
5343
- log("[analytics] Failed to end session (non-fatal)", { error: String(err) });
5353
+ log("[analytics] Failed to end session (non-fatal)", {
5354
+ error: String(err)
5355
+ });
5344
5356
  }
5345
5357
  if (directory) {
5346
5358
  try {
@@ -5447,7 +5459,10 @@ ${cmdResult.contextInjection}`;
5447
5459
  agent: result.switchAgent
5448
5460
  });
5449
5461
  } catch (err) {
5450
- log("[workflow] Failed to inject workflow continuation", { sessionId, error: String(err) });
5462
+ log("[workflow] Failed to inject workflow continuation", {
5463
+ sessionId,
5464
+ error: String(err)
5465
+ });
5451
5466
  }
5452
5467
  return;
5453
5468
  }
@@ -5467,10 +5482,15 @@ ${cmdResult.contextInjection}`;
5467
5482
  parts: [{ type: "text", text: result.continuationPrompt }]
5468
5483
  }
5469
5484
  });
5470
- log("[work-continuation] Injected continuation prompt", { sessionId });
5485
+ log("[work-continuation] Injected continuation prompt", {
5486
+ sessionId
5487
+ });
5471
5488
  continuationFired = true;
5472
5489
  } catch (err) {
5473
- log("[work-continuation] Failed to inject continuation", { sessionId, error: String(err) });
5490
+ log("[work-continuation] Failed to inject continuation", {
5491
+ sessionId,
5492
+ error: String(err)
5493
+ });
5474
5494
  }
5475
5495
  } else if (result.continuationPrompt) {
5476
5496
  log("[work-continuation] continuationPrompt available but no client", { sessionId });
@@ -5482,7 +5502,9 @@ ${cmdResult.contextInjection}`;
5482
5502
  const sessionId = evt.properties?.sessionID ?? "";
5483
5503
  if (sessionId && !todoFinalizedSessions.has(sessionId)) {
5484
5504
  try {
5485
- const todosResponse = await client.session.todo({ path: { id: sessionId } });
5505
+ const todosResponse = await client.session.todo({
5506
+ path: { id: sessionId }
5507
+ });
5486
5508
  const todos = todosResponse.data ?? [];
5487
5509
  const hasInProgress = todos.some((t) => t.status === "in_progress");
5488
5510
  if (hasInProgress) {
@@ -5510,7 +5532,10 @@ Use todowrite NOW to mark all of them as "completed" (or "cancelled" if abandone
5510
5532
  });
5511
5533
  }
5512
5534
  } catch (err) {
5513
- log("[todo-finalize] Failed to check/finalize todos (non-fatal)", { sessionId, error: String(err) });
5535
+ log("[todo-finalize] Failed to check/finalize todos (non-fatal)", {
5536
+ sessionId,
5537
+ error: String(err)
5538
+ });
5514
5539
  }
5515
5540
  }
5516
5541
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a4hgehad/weave-mcp",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Weave-MCP — lean OpenCode plugin with multi-agent orchestration and MCP support",
5
5
  "author": "3r3bu5",
6
6
  "license": "MIT",