@codemieai/code 0.4.0 → 0.4.1

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.
@@ -5,5 +5,5 @@
5
5
  "name": "AI/Run CodeMie",
6
6
  "email": "support@codemieai.com"
7
7
  },
8
- "version": "1.0.23"
8
+ "version": "1.0.25"
9
9
  }
@@ -2,14 +2,15 @@
2
2
  name: msgraph
3
3
  description: >
4
4
  Work with Microsoft 365 services via the Graph API — emails, calendar events, SharePoint sites
5
- (read and write), Teams chats and channel messages, OneDrive files, OneNote notebooks, contacts,
6
- and org chart. Use this skill whenever the user asks about their emails, inbox, unread messages,
7
- meetings, calendar, Teams messages or chats, channel messages, SharePoint documents, OneDrive
8
- files, OneNote notes or notebooks, colleagues, manager, direct reports, or any
9
- personal/organizational Microsoft data. Invoke proactively any time the user mentions Outlook,
10
- Teams, SharePoint, OneDrive, OneNote, or wants to interact with their Microsoft 365 account.
11
- The skill uses a local Node.js CLI (msgraph.js) that handles authentication, token caching,
12
- and all API calls.
5
+ (read and write), Teams chats and channel messages, OneDrive files, OneNote notebooks, Planner
6
+ task boards, Microsoft To Do task lists, AI meeting insights (Copilot recap), contacts, and org
7
+ chart. Use this skill whenever the user asks about their emails, inbox, unread messages, meetings,
8
+ calendar, Teams messages or chats, channel messages, SharePoint documents, OneDrive files, OneNote
9
+ notes or notebooks, Planner plans or tasks, "my tasks", to-do lists, action items, meeting
10
+ summaries, colleagues, manager, direct reports, or any personal/organizational Microsoft data.
11
+ Invoke proactively any time the user mentions Outlook, Teams, SharePoint, OneDrive, OneNote,
12
+ Planner, Microsoft To Do, or wants to interact with their Microsoft 365 account. The skill uses a
13
+ local Node.js CLI (msgraph.js) that handles authentication, token caching, and all API calls.
13
14
  ---
14
15
 
15
16
  # Microsoft Graph API Skill
@@ -199,6 +200,61 @@ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js onenote --create "M
199
200
  node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js onenote --notebooks --json
200
201
  ```
201
202
 
203
+ ### Planner
204
+
205
+ Team/group task boards. Plans live inside Microsoft 365 groups, so `--plans` needs the
206
+ `Group.Read.All` scope. Updates use optimistic concurrency under the hood (etag handling is
207
+ automatic).
208
+
209
+ ```bash
210
+ # List all plans shared with you (one call)
211
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js planner --plans
212
+
213
+ # Tasks assigned to you across all plans (the usual starting point)
214
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js planner --my-tasks
215
+
216
+ # List tasks in a specific plan (use ID from --plans)
217
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js planner --plan-id PLAN_ID --tasks
218
+
219
+ # List buckets (columns) in a plan
220
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js planner --plan-id PLAN_ID --buckets
221
+
222
+ # Show one task's details (description, % complete, due date)
223
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js planner --task-id TASK_ID
224
+
225
+ # Create a task in a plan (bucket, due date and assignee are optional)
226
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js planner --plan-id PLAN_ID \
227
+ --create "Write release notes" --bucket-id BUCKET_ID --due 2026-06-20 --assign USER_AAD_ID
228
+
229
+ # Mark a task complete (reads the etag, then sets it to 100%)
230
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js planner --complete TASK_ID
231
+
232
+ # Machine-readable JSON output (on any read command)
233
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js planner --my-tasks --json
234
+ ```
235
+
236
+ > `--my-tasks` returns only `planId`/`bucketId` (no names). To turn an ID into a readable
237
+ > plan name, run `planner --plans`. Use `people --search NAME` to get a user's AAD ID for `--assign`.
238
+
239
+ ### To Do
240
+
241
+ Personal Microsoft To Do task lists (simpler than Planner — flat lists of tasks).
242
+
243
+ ```bash
244
+ # List your task lists
245
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js todo --lists
246
+
247
+ # List tasks in a list (use ID from --lists)
248
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js todo --list-id LIST_ID --tasks
249
+
250
+ # Create a task
251
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js todo --list-id LIST_ID \
252
+ --create "Renew certificate" --body "Before it expires" --due 2026-06-15
253
+
254
+ # Mark a task complete
255
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js todo --list-id LIST_ID --complete TASK_ID
256
+ ```
257
+
202
258
  ### Channels
203
259
 
204
260
  ```bash
@@ -235,8 +291,18 @@ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js transcripts --meeti
235
291
 
236
292
  # Download as VTT (timestamped captions format)
237
293
  node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js transcripts --meeting MEETING_ID --transcript TRANSCRIPT_ID --vtt --output meeting.vtt
294
+
295
+ # AI meeting recap (Copilot-generated notes, action items, mentions) for a known meeting
296
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js transcripts --meeting MEETING_ID --insights
297
+
298
+ # AI recap by date + subject (resolves the meeting for you)
299
+ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js transcripts --start 2026-06-09 --subject "planning" --insights
238
300
  ```
239
301
 
302
+ > **AI Insights require a Microsoft 365 Copilot license.** Insights are generated only after a
303
+ > meeting ends (with transcription/recording on) and can take up to 4 hours to appear. A `403`
304
+ > means the Copilot license is missing; an empty result means insights aren't ready yet.
305
+
240
306
  ### People & Contacts
241
307
 
242
308
  ```bash
@@ -296,6 +362,27 @@ node ${CLAUDE_PLUGIN_ROOT}/skills/msgraph/scripts/msgraph.js people --contacts
296
362
  ### "Who's my manager?" / "Who reports to me?"
297
363
  - Run `org --manager` or `org --reports`
298
364
 
365
+ ### "What are my tasks?" / "What's on my Planner?"
366
+ 1. Run `planner --my-tasks` → tasks assigned to you across all plans
367
+ 2. Run `planner --plans` to map any `planId` in the output to a readable plan name
368
+ 3. Drill in with `planner --plan-id PLAN_ID --tasks` if the user wants a specific board
369
+ 4. Also check `todo --lists` then `todo --list-id LIST_ID --tasks` for personal To Do items
370
+
371
+ ### "Add a task to Planner" / "Create a to-do"
372
+ 1. Planner: run `planner --plans` (then `--buckets` if a column is needed) to get IDs, then
373
+ `planner --plan-id PLAN_ID --create "TITLE"` (add `--due`, `--assign`, `--bucket-id` as needed)
374
+ 2. To Do: run `todo --lists`, then `todo --list-id LIST_ID --create "TITLE"`
375
+
376
+ ### "Mark that task done"
377
+ - Planner: `planner --complete TASK_ID` · To Do: `todo --list-id LIST_ID --complete TASK_ID`
378
+
379
+ ### "Summarize yesterday's meeting" / "What were the action items?"
380
+ 1. Run `transcripts --start YYYY-MM-DD --subject "keyword" --insights` (resolves the meeting and
381
+ prints Copilot notes, action items, and mentions)
382
+ 2. Or, with a known meeting ID: `transcripts --meeting MEETING_ID --insights`
383
+ 3. If you get a `403`, tell the user a Microsoft 365 Copilot license is required; if empty, insights
384
+ may not be ready yet (up to 4 hours after the meeting ends)
385
+
299
386
  ---
300
387
 
301
388
  ## Error Handling
@@ -44,10 +44,12 @@ const SCOPES = [
44
44
  'ChannelMessage.Read.All', 'ChannelMessage.Send',
45
45
  'OnlineMeetingTranscript.Read.All', 'OnlineMeetings.Read',
46
46
  'People.Read', 'Contacts.Read', 'offline_access',
47
- 'Notes.Read', 'Notes.ReadWrite',
47
+ 'Notes.Read', 'Notes.ReadWrite', 'OnlineMeetingAiInsight.Read.All', 'Tasks.ReadWrite',
48
+ 'Group.Read.All',
48
49
  ].join(' ');
49
50
  const CACHE_FILE = path.join(os.homedir(), '.ms_graph_token_cache.json');
50
51
  const GRAPH_BASE = 'https://graph.microsoft.com/v1.0';
52
+ const GRAPH_BETA = 'https://graph.microsoft.com/beta';
51
53
  const TIMEOUT_MS = 5 * 60 * 1000;
52
54
 
53
55
  // ── HTTP Helpers ──────────────────────────────────────────────────────────────
@@ -112,6 +114,21 @@ async function graphPost(endpoint, token, body) {
112
114
  return res.body ? JSON.parse(res.body) : {};
113
115
  }
114
116
 
117
+ async function graphPatch(endpoint, token, body, extraHeaders = {}) {
118
+ const bodyStr = JSON.stringify(body);
119
+ const res = await httpsRequest(`${GRAPH_BASE}${endpoint}`, {
120
+ method: 'PATCH',
121
+ headers: {
122
+ Authorization: `Bearer ${token}`,
123
+ 'Content-Type': 'application/json',
124
+ 'Content-Length': Buffer.byteLength(bodyStr),
125
+ ...extraHeaders,
126
+ },
127
+ }, bodyStr);
128
+ // Planner PATCH returns 204 with an empty body unless Prefer: return=representation is sent.
129
+ return res.body ? JSON.parse(res.body) : {};
130
+ }
131
+
115
132
  function graphDownload(endpoint, token) {
116
133
  function fetch(url, auth) {
117
134
  return new Promise((resolve, reject) => {
@@ -342,6 +359,15 @@ function fmtDt(iso) {
342
359
  catch { return (iso || '').slice(0, 16).replace('T', ' '); }
343
360
  }
344
361
 
362
+ // Formats a Graph dateTimeTimeZone object ({ dateTime, timeZone }). To Do returns a
363
+ // zone-less dateTime, so a UTC value would otherwise be parsed as local time by fmtDt.
364
+ function fmtDtTz(dtz) {
365
+ if (!dtz?.dateTime) return 'N/A';
366
+ let s = dtz.dateTime;
367
+ if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(s) && (dtz.timeZone || '').toUpperCase() === 'UTC') s += 'Z';
368
+ return fmtDt(s);
369
+ }
370
+
345
371
  function fmtSize(n) {
346
372
  if (!n) return '';
347
373
  const units = ['B', 'KB', 'MB', 'GB', 'TB'];
@@ -750,9 +776,135 @@ async function cmdChannels(args) {
750
776
  console.log(' --team-id ID --channel-id ID --send MSG');
751
777
  }
752
778
 
779
+ // ── Meeting AI Insights (Copilot recap) ────────────────────────────────────────
780
+ // Lives in the Microsoft 365 Copilot API namespace and is keyed by user object ID
781
+ // (not /me). The aiInsights navigation is documented under beta, so try v1.0 first
782
+ // and fall back to beta on 404. Requires a Microsoft 365 Copilot license.
783
+ async function getAiInsights(token, oid, meetingId, insightId) {
784
+ const suffix = insightId ? `/${insightId}` : '';
785
+ const ep = `/copilot/users/${oid}/onlineMeetings/${meetingId}/aiInsights${suffix}`;
786
+ const headers = { Authorization: `Bearer ${token}` };
787
+ try {
788
+ const res = await httpsRequest(`${GRAPH_BASE}${ep}`, { headers });
789
+ return JSON.parse(res.body);
790
+ } catch (err) {
791
+ if (err.statusCode === 404) {
792
+ const res = await httpsRequest(`${GRAPH_BETA}${ep}`, { headers });
793
+ return JSON.parse(res.body);
794
+ }
795
+ throw err;
796
+ }
797
+ }
798
+
799
+ async function printMeetingInsights(token, oid, meetingId, args) {
800
+ let list;
801
+ try {
802
+ list = await getAiInsights(token, oid, meetingId);
803
+ } catch (err) {
804
+ if (err.statusCode === 403) {
805
+ console.error('AI insights require a Microsoft 365 Copilot license (and transcription/recording enabled for the meeting).');
806
+ return;
807
+ }
808
+ if (err.statusCode === 404) {
809
+ console.log('No AI insights available for this meeting (none generated yet, or unsupported meeting type).');
810
+ return;
811
+ }
812
+ throw err;
813
+ }
814
+
815
+ const insights = list.value || [];
816
+ if (!insights.length) {
817
+ console.log('No AI insights yet. Insights generate after the meeting ends and can take up to 4 hours.');
818
+ return;
819
+ }
820
+
821
+ const full = [];
822
+ for (const ins of insights) {
823
+ try { full.push(await getAiInsights(token, oid, meetingId, ins.id)); }
824
+ catch { full.push(ins); }
825
+ }
826
+
827
+ if (args.json) { console.log(JSON.stringify(full, null, 2)); return; }
828
+
829
+ for (const ai of full) {
830
+ console.log(`\n${'═'.repeat(60)}`);
831
+ console.log(`AI Insight ${ai.id || ''} (${fmtDt(ai.createdDateTime)})`);
832
+
833
+ const notes = ai.meetingNotes || [];
834
+ if (notes.length) {
835
+ console.log('\nMeeting Notes:');
836
+ for (const n of notes) {
837
+ console.log(` • ${n.title || ''}`);
838
+ if (n.text) console.log(` ${n.text}`);
839
+ for (const sp of n.subpoints || []) {
840
+ console.log(` – ${sp.title || ''}`);
841
+ if (sp.text) console.log(` ${sp.text}`);
842
+ }
843
+ }
844
+ }
845
+
846
+ const items = ai.actionItems || [];
847
+ if (items.length) {
848
+ console.log('\nAction Items:');
849
+ for (const it of items)
850
+ console.log(` ☐ ${it.title || ''}${it.ownerDisplayName ? ` (owner: ${it.ownerDisplayName})` : ''}`);
851
+ }
852
+
853
+ const mentions = ai.viewpoint?.mentionEvents || [];
854
+ if (mentions.length) {
855
+ console.log('\nMentions:');
856
+ for (const m of mentions)
857
+ console.log(` @ ${fmtDt(m.eventDateTime)} ${m.speaker?.user?.displayName || ''}: ${(m.transcriptUtterance || '').slice(0, 200)}`);
858
+ }
859
+ }
860
+ }
861
+
862
+ async function cmdTranscriptsInsights(args, token) {
863
+ const me = await graphGet('/me', token, { $select: 'id' });
864
+ const oid = me.id;
865
+
866
+ // Direct meeting ID short-circuits resolution.
867
+ if (args.meeting) {
868
+ await printMeetingInsights(token, oid, args.meeting, args);
869
+ return;
870
+ }
871
+
872
+ // Otherwise resolve online meetings via the calendar (same approach as --subject).
873
+ const startDate = args.start || new Date(Date.now() - 7 * 86400 * 1000).toISOString().slice(0, 10);
874
+ const endDate = args.end || startDate;
875
+ const data = await graphGet('/me/calendarView', token, {
876
+ startDateTime: startDate + 'T00:00:00Z',
877
+ endDateTime: endDate + 'T23:59:59Z',
878
+ $select: 'subject,start,isOnlineMeeting,onlineMeeting',
879
+ $top: 50,
880
+ $orderby: 'start/dateTime',
881
+ });
882
+ let events = (data.value || []).filter(e => e.isOnlineMeeting && e.onlineMeeting?.joinUrl);
883
+ if (args.subject) {
884
+ const kw = args.subject.toLowerCase();
885
+ events = events.filter(e => (e.subject || '').toLowerCase().includes(kw));
886
+ }
887
+ if (!events.length) { console.log('No matching online meetings found in range.'); return; }
888
+
889
+ for (const e of events) {
890
+ let meetingId = null;
891
+ try {
892
+ const om = await graphGet('/me/onlineMeetings', token, { $filter: `joinWebUrl eq '${e.onlineMeeting.joinUrl}'` });
893
+ meetingId = (om.value || [])[0]?.id || null;
894
+ } catch (err) {
895
+ console.log(`Could not resolve meeting ID for "${e.subject}": ${err.message}`);
896
+ }
897
+ if (!meetingId) continue;
898
+ console.log(`\nMeeting: ${e.subject} (${fmtDt(e.start?.dateTime)}) — ${meetingId}`);
899
+ await printMeetingInsights(token, oid, meetingId, args);
900
+ }
901
+ }
902
+
753
903
  async function cmdTranscripts(args) {
754
904
  const token = await getValidToken();
755
905
 
906
+ if (args.insights) return cmdTranscriptsInsights(args, token);
907
+
756
908
  if (args.list || (!args.meeting && !args.download)) {
757
909
  const startDate = args.start || new Date(Date.now() - 7 * 86400 * 1000).toISOString().slice(0, 10);
758
910
  const endDate = args.end || startDate;
@@ -1161,10 +1313,179 @@ async function cmdOnenote(args) {
1161
1313
  console.log(' --create TITLE --section SECTION_ID [--body CONTENT]');
1162
1314
  }
1163
1315
 
1316
+ async function cmdPlanner(args) {
1317
+ const token = await getValidToken();
1318
+ const limit = parseInt(args.limit) || 20;
1319
+
1320
+ // Plans shared with me (single call; plans live in M365 groups → needs Group.Read.All).
1321
+ // Planner rejects OData params ($top/$select/$filter return HTTP 400) — fetch all, slice client-side.
1322
+ if (args.plans) {
1323
+ const data = await graphGet('/me/planner/plans', token);
1324
+ const plans = (data.value || []).slice(0, limit);
1325
+ if (args.json) { console.log(JSON.stringify(plans, null, 2)); return; }
1326
+ if (!plans.length) { console.log('No plans found.'); return; }
1327
+ console.log(`\n${'Plan ID'.padEnd(30)} Title`);
1328
+ console.log('─'.repeat(70));
1329
+ for (const p of plans)
1330
+ console.log(`${(p.id || '').padEnd(30)} ${p.title || '(untitled)'}`);
1331
+ return;
1332
+ }
1333
+
1334
+ // Tasks assigned to me (returns planId/bucketId only — no names). No OData params on Planner.
1335
+ if (args.myTasks) {
1336
+ const data = await graphGet('/me/planner/tasks', token);
1337
+ const tasks = (data.value || []).slice(0, limit);
1338
+ if (args.json) { console.log(JSON.stringify(tasks, null, 2)); return; }
1339
+ if (!tasks.length) { console.log('No tasks assigned to you.'); return; }
1340
+ console.log(`\n${'Task ID'.padEnd(30)} ${'%'.padEnd(4)} ${'Due'.padEnd(16)} Title`);
1341
+ console.log('─'.repeat(80));
1342
+ for (const t of tasks) {
1343
+ const due = t.dueDateTime ? fmtDt(t.dueDateTime) : '';
1344
+ console.log(`${(t.id || '').padEnd(30)} ${String(t.percentComplete ?? 0).padEnd(4)} ${pad(due, 16)} ${t.title || '(untitled)'}`);
1345
+ }
1346
+ return;
1347
+ }
1348
+
1349
+ // Buckets (columns) in a plan.
1350
+ if (args.planId && args.buckets) {
1351
+ const data = await graphGet(`/planner/plans/${args.planId}/buckets`, token);
1352
+ const buckets = data.value || [];
1353
+ if (args.json) { console.log(JSON.stringify(buckets, null, 2)); return; }
1354
+ if (!buckets.length) { console.log('No buckets found.'); return; }
1355
+ console.log(`\n${'Bucket ID'.padEnd(30)} Name`);
1356
+ console.log('─'.repeat(70));
1357
+ for (const b of buckets)
1358
+ console.log(`${(b.id || '').padEnd(30)} ${b.name || '(unnamed)'}`);
1359
+ return;
1360
+ }
1361
+
1362
+ // Create a task in a plan.
1363
+ if (args.planId && typeof args.create === 'string') {
1364
+ const payload = { planId: args.planId, title: args.create };
1365
+ if (args.bucketId) payload.bucketId = args.bucketId;
1366
+ if (args.due) payload.dueDateTime = `${args.due}T00:00:00Z`;
1367
+ if (args.assign) {
1368
+ payload.assignments = {
1369
+ [args.assign]: { '@odata.type': '#microsoft.graph.plannerAssignment', orderHint: ' !' },
1370
+ };
1371
+ }
1372
+ const task = await graphPost('/planner/tasks', token, payload);
1373
+ console.log(`Task created: ${task.title || args.create}`);
1374
+ console.log(`ID: ${task.id}`);
1375
+ return;
1376
+ }
1377
+
1378
+ // Tasks in a plan. No OData params on Planner.
1379
+ if (args.planId && args.tasks) {
1380
+ const data = await graphGet(`/planner/plans/${args.planId}/tasks`, token);
1381
+ const tasks = (data.value || []).slice(0, limit);
1382
+ if (args.json) { console.log(JSON.stringify(tasks, null, 2)); return; }
1383
+ if (!tasks.length) { console.log('No tasks in this plan.'); return; }
1384
+ console.log(`\n${'Task ID'.padEnd(30)} ${'%'.padEnd(4)} ${'Due'.padEnd(16)} Title`);
1385
+ console.log('─'.repeat(80));
1386
+ for (const t of tasks) {
1387
+ const due = t.dueDateTime ? fmtDt(t.dueDateTime) : '';
1388
+ console.log(`${(t.id || '').padEnd(30)} ${String(t.percentComplete ?? 0).padEnd(4)} ${pad(due, 16)} ${t.title || '(untitled)'}`);
1389
+ }
1390
+ return;
1391
+ }
1392
+
1393
+ // Mark a task complete: read its etag, then PATCH percentComplete to 100.
1394
+ if (typeof args.complete === 'string') {
1395
+ const task = await graphGet(`/planner/tasks/${args.complete}`, token);
1396
+ const etag = task['@odata.etag'];
1397
+ if (!etag) { console.error('Could not read the task etag; cannot update.'); process.exit(1); }
1398
+ await graphPatch(`/planner/tasks/${args.complete}`, token, { percentComplete: 100 }, { 'If-Match': etag });
1399
+ console.log(`Task marked complete: ${task.title || args.complete}`);
1400
+ return;
1401
+ }
1402
+
1403
+ // Single task detail (+ description/checklist from /details).
1404
+ if (args.taskId) {
1405
+ const task = await graphGet(`/planner/tasks/${args.taskId}`, token);
1406
+ let details = {};
1407
+ try { details = await graphGet(`/planner/tasks/${args.taskId}/details`, token); } catch {}
1408
+ if (args.json) { console.log(JSON.stringify({ ...task, details }, null, 2)); return; }
1409
+ console.log(`Title : ${task.title || '(untitled)'}`);
1410
+ console.log(`% Complete : ${task.percentComplete ?? 0}`);
1411
+ console.log(`Due : ${task.dueDateTime ? fmtDt(task.dueDateTime) : 'N/A'}`);
1412
+ console.log(`Bucket ID : ${task.bucketId || 'N/A'}`);
1413
+ console.log(`Plan ID : ${task.planId || 'N/A'}`);
1414
+ if (details.description) console.log(`\nDescription:\n${details.description}`);
1415
+ return;
1416
+ }
1417
+
1418
+ console.log('Planner: --plans | --my-tasks');
1419
+ console.log(' --plan-id ID --tasks | --plan-id ID --buckets');
1420
+ console.log(' --plan-id ID --create "TITLE" [--bucket-id ID] [--due YYYY-MM-DD] [--assign USER_ID]');
1421
+ console.log(' --task-id ID | --complete TASK_ID');
1422
+ }
1423
+
1424
+ async function cmdTodo(args) {
1425
+ const token = await getValidToken();
1426
+ const limit = parseInt(args.limit) || 20;
1427
+
1428
+ if (args.lists) {
1429
+ const data = await graphGet('/me/todo/lists', token, { $top: limit });
1430
+ const lists = data.value || [];
1431
+ if (args.json) { console.log(JSON.stringify(lists, null, 2)); return; }
1432
+ if (!lists.length) { console.log('No task lists found.'); return; }
1433
+ console.log(`\n${'List ID'.padEnd(50)} Name`);
1434
+ console.log('─'.repeat(80));
1435
+ for (const l of lists)
1436
+ console.log(`${(l.id || '').padEnd(50)} ${l.displayName || '(unnamed)'}`);
1437
+ return;
1438
+ }
1439
+
1440
+ if (!args.listId) {
1441
+ console.log('To Do: --lists');
1442
+ console.log(' --list-id ID --tasks');
1443
+ console.log(' --list-id ID --create "TITLE" [--body TEXT] [--due YYYY-MM-DD]');
1444
+ console.log(' --list-id ID --complete TASK_ID');
1445
+ return;
1446
+ }
1447
+
1448
+ // Create a task in a list.
1449
+ if (typeof args.create === 'string') {
1450
+ const payload = { title: args.create };
1451
+ if (args.body) payload.body = { content: args.body, contentType: 'text' };
1452
+ if (args.due) payload.dueDateTime = { dateTime: `${args.due}T00:00:00.000000`, timeZone: 'UTC' };
1453
+ const task = await graphPost(`/me/todo/lists/${args.listId}/tasks`, token, payload);
1454
+ console.log(`Task created: ${task.title || args.create}`);
1455
+ console.log(`ID: ${task.id}`);
1456
+ return;
1457
+ }
1458
+
1459
+ // Mark a task complete (To Do needs no etag).
1460
+ if (typeof args.complete === 'string') {
1461
+ await graphPatch(`/me/todo/lists/${args.listId}/tasks/${args.complete}`, token, { status: 'completed' });
1462
+ console.log(`Task marked complete: ${args.complete}`);
1463
+ return;
1464
+ }
1465
+
1466
+ // Tasks in a list.
1467
+ if (args.tasks) {
1468
+ const data = await graphGet(`/me/todo/lists/${args.listId}/tasks`, token, { $top: limit });
1469
+ const tasks = data.value || [];
1470
+ if (args.json) { console.log(JSON.stringify(tasks, null, 2)); return; }
1471
+ if (!tasks.length) { console.log('No tasks in this list.'); return; }
1472
+ console.log(`\n${'Task ID'.padEnd(50)} ${'Status'.padEnd(12)} Title`);
1473
+ console.log('─'.repeat(80));
1474
+ for (const t of tasks) {
1475
+ const due = t.dueDateTime?.dateTime ? ` (due ${fmtDtTz(t.dueDateTime)})` : '';
1476
+ console.log(`${(t.id || '').padEnd(50)} ${(t.status || '').padEnd(12)} ${t.title || '(untitled)'}${due}`);
1477
+ }
1478
+ return;
1479
+ }
1480
+
1481
+ console.log('To Do: --list-id ID --tasks | --create "TITLE" | --complete TASK_ID');
1482
+ }
1483
+
1164
1484
  // ── CLI Parser ────────────────────────────────────────────────────────────────
1165
1485
  function parseArgs(argv) {
1166
1486
  const BOOL = new Set(['json','unread','sites','chats','teamsList','contacts',
1167
- 'manager','reports','availability','notebooks','list','messages','vtt','help','force']);
1487
+ 'manager','reports','availability','notebooks','list','messages','vtt','help','force',
1488
+ 'plans','buckets','tasks','myTasks','lists','insights']);
1168
1489
  const args = { _: [] };
1169
1490
  let i = 0;
1170
1491
  while (i < argv.length) {
@@ -1216,8 +1537,16 @@ Data:
1216
1537
  onenote [--notebooks] [--sections NOTEBOOK_ID] [--pages SECTION_ID]
1217
1538
  [--read PAGE_ID] [--search QUERY] [--limit N] [--json]
1218
1539
  [--create TITLE --section SECTION_ID [--body CONTENT]]
1540
+ planner [--plans] [--my-tasks]
1541
+ [--plan-id ID --tasks] [--plan-id ID --buckets]
1542
+ [--plan-id ID --create "TITLE" [--bucket-id ID] [--due YYYY-MM-DD] [--assign USER_ID]]
1543
+ [--task-id ID] [--complete TASK_ID] [--json]
1544
+ todo [--lists] [--list-id ID --tasks]
1545
+ [--list-id ID --create "TITLE" [--body TEXT] [--due YYYY-MM-DD]]
1546
+ [--list-id ID --complete TASK_ID] [--json]
1219
1547
  transcripts [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--subject KEYWORD]
1220
1548
  [--meeting ID] [--transcript ID] [--output FILE] [--vtt]
1549
+ [--insights] (AI meeting recap — requires Microsoft 365 Copilot)
1221
1550
 
1222
1551
  Add --json to any command for machine-readable output.
1223
1552
  `);
@@ -1245,6 +1574,8 @@ async function main() {
1245
1574
  people: () => cmdPeople(args),
1246
1575
  org: () => cmdOrg(args),
1247
1576
  onenote: () => cmdOnenote(args),
1577
+ planner: () => cmdPlanner(args),
1578
+ todo: () => cmdTodo(args),
1248
1579
  transcripts: () => cmdTranscripts(args),
1249
1580
  claims: () => cmdClaims(args),
1250
1581
  help: () => { printHelp(); process.exit(0); },
@@ -1 +1 @@
1
- {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/analytics/exporter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAWrE;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IA8DpE;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;CAKzE"}
1
+ {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/analytics/exporter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAWrE;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IA8DpE;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;CAIzE"}
@@ -2,6 +2,7 @@
2
2
  * Export functionality for analytics data
3
3
  */
4
4
  import { writeFileSync } from 'fs';
5
+ import { join } from 'path';
5
6
  import chalk from 'chalk';
6
7
  export class AnalyticsExporter {
7
8
  /**
@@ -84,8 +85,7 @@ export class AnalyticsExporter {
84
85
  */
85
86
  static getDefaultOutputPath(format, cwd) {
86
87
  const timestamp = new Date().toISOString().split('T')[0];
87
- const filename = `codemie-analytics-${timestamp}.${format}`;
88
- return `${cwd}/${filename}`;
88
+ return join(cwd, `codemie-analytics-${timestamp}.${format}`);
89
89
  }
90
90
  }
91
91
  //# sourceMappingURL=exporter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"exporter.js","sourceRoot":"","sources":["../../../../src/cli/commands/analytics/exporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"exporter.js","sourceRoot":"","sources":["../../../../src/cli/commands/analytics/exporter.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/analytics/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,sBAAsB,IAAI,OAAO,CAwKhD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/analytics/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,sBAAsB,IAAI,OAAO,CAgMhD"}
@@ -99,7 +99,7 @@ export function createAnalyticsCommand() {
99
99
  // Generate the report if requested (--report-output and --open imply --report)
100
100
  if (wantReport && costResult) {
101
101
  const { buildPayload } = await import('./report/payload-builder.js');
102
- const { generateReport, generateReportJson, getDefaultReportPath, getDefaultReportJsonPath } = await import('./report/report-generator.js');
102
+ const { generateReport, generateReportJson, getDefaultReportPath, getDefaultReportJsonPath, writeReportWithFallback } = await import('./report/report-generator.js');
103
103
  const { index: costIndex, summary } = costResult;
104
104
  const payload = buildPayload(analytics, costIndex, summary, {
105
105
  rangeLabel: options.last ?? (options.from || options.to ? 'custom' : 'all'),
@@ -109,25 +109,40 @@ export function createAnalyticsCommand() {
109
109
  const cwd = process.cwd();
110
110
  let htmlPath;
111
111
  let jsonPath;
112
+ // Default (cwd-derived) paths may relocate when cwd is unwritable (drive root,
113
+ // read-only volume); an explicit --report-output is honored as-is, errors included.
114
+ let htmlIsDefault = false;
115
+ let jsonIsDefault = false;
112
116
  if (reportFormat === 'both') {
113
117
  // Derive a shared base (strip a trailing .html/.json from --report-output, if any)
114
118
  // so the two artifacts are siblings and never collide, whatever extension was passed.
115
119
  const base = options.reportOutput?.replace(/\.(html|json)$/i, '');
116
120
  htmlPath = base ? `${base}.html` : getDefaultReportPath(cwd);
117
121
  jsonPath = base ? `${base}.json` : getDefaultReportJsonPath(cwd);
122
+ htmlIsDefault = jsonIsDefault = !base;
118
123
  }
119
124
  else if (reportFormat === 'html') {
120
125
  htmlPath = options.reportOutput || getDefaultReportPath(cwd);
126
+ htmlIsDefault = !options.reportOutput;
121
127
  }
122
128
  else {
123
129
  jsonPath = options.reportOutput || getDefaultReportJsonPath(cwd);
130
+ jsonIsDefault = !options.reportOutput;
124
131
  }
125
132
  if (htmlPath) {
126
- generateReport(payload, htmlPath);
133
+ const result = writeReportWithFallback((p) => generateReport(payload, p), htmlPath, htmlIsDefault);
134
+ htmlPath = result.path; // keep --open and the success line pointed at the real file
135
+ if (result.relocatedFrom) {
136
+ console.log(chalk.yellow(`\n! ${result.relocatedFrom} is not writable (drive root or read-only volume); using a writable location instead.`));
137
+ }
127
138
  console.log(chalk.green(`\n✓ HTML report written to: ${htmlPath}`));
128
139
  }
129
140
  if (jsonPath) {
130
- generateReportJson(payload, jsonPath);
141
+ const result = writeReportWithFallback((p) => generateReportJson(payload, p), jsonPath, jsonIsDefault);
142
+ jsonPath = result.path;
143
+ if (result.relocatedFrom) {
144
+ console.log(chalk.yellow(`\n! ${result.relocatedFrom} is not writable (drive root or read-only volume); using a writable location instead.`));
145
+ }
131
146
  console.log(chalk.green(`\n✓ JSON report written to: ${jsonPath}`));
132
147
  }
133
148
  const { sessions: totalReportSessions, pricedSessions } = payload.meta.totals;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cli/commands/analytics/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cli/commands/analytics/index.ts"],"names":[],"mappings":"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"}
@@ -23,4 +23,25 @@ export declare function generateReport(payload: ReportPayload, outputPath: strin
23
23
  export declare function generateReportJson(payload: ReportPayload, outputPath: string): void;
24
24
  export declare function getDefaultReportPath(cwd: string): string;
25
25
  export declare function getDefaultReportJsonPath(cwd: string): string;
26
+ /**
27
+ * Permission / read-only fs errors that a *different output directory* can resolve.
28
+ * Seen when the report defaults to a cwd that is a drive root (Windows `D:\`) or a
29
+ * read-only / write-protected volume (removable, network, BitLocker-locked, etc.).
30
+ */
31
+ export declare function isUnwritableLocationError(err: unknown): boolean;
32
+ /** Result of {@link writeReportWithFallback}: where the file actually landed. */
33
+ export interface ReportWriteResult {
34
+ /** The path the report was finally written to. */
35
+ path: string;
36
+ /** Set only when the preferred path was unwritable and we relocated. */
37
+ relocatedFrom?: string;
38
+ }
39
+ /**
40
+ * Writes a report via `write(path)`. If the preferred location is unwritable
41
+ * (drive root, read-only volume) AND `allowFallback` is true, retries the same
42
+ * filename under the user's home dir, then the OS temp dir, and reports where it
43
+ * landed. With `allowFallback` false (an explicit `--report-output`) or for any
44
+ * non-permission error, the original error propagates unchanged.
45
+ */
46
+ export declare function writeReportWithFallback(write: (path: string) => void, preferredPath: string, allowFallback: boolean): ReportWriteResult;
26
47
  //# sourceMappingURL=report-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"report-generator.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/report/report-generator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAkBT;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAO/E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAEnF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK5D"}
1
+ {"version":3,"file":"report-generator.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/report/report-generator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAkBT;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAQ/E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAGnF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG/D;AAED,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAC7B,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,OAAO,GACrB,iBAAiB,CAmBnB"}
@@ -3,8 +3,9 @@
3
3
  * the analytics payload as valid JS, and inline the client app. No server, no
4
4
  * external data files — the result opens anywhere.
5
5
  */
6
- import { readFileSync, writeFileSync } from 'node:fs';
7
- import { join } from 'node:path';
6
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
7
+ import { homedir, tmpdir } from 'node:os';
8
+ import { basename, dirname, join } from 'node:path';
8
9
  import { getDirname } from '../../../../utils/paths.js';
9
10
  const HERE = getDirname(import.meta.url); // dist/.../analytics/report at runtime
10
11
  /** Pure string assembly — unit-testable without fs. */
@@ -34,6 +35,7 @@ export function generateReport(payload, outputPath) {
34
35
  const chartJs = readFileSync(join(HERE, 'assets', 'chart.umd.js'), 'utf-8');
35
36
  const clientJs = readFileSync(join(HERE, 'client', 'app.js'), 'utf-8');
36
37
  const html = renderReportHtml({ template, css, chartJs, clientJs, payload });
38
+ mkdirSync(dirname(outputPath), { recursive: true });
37
39
  writeFileSync(outputPath, html, 'utf-8');
38
40
  }
39
41
  /**
@@ -43,16 +45,58 @@ export function generateReport(payload, outputPath) {
43
45
  * only and must NOT be applied to a .json file on disk.
44
46
  */
45
47
  export function generateReportJson(payload, outputPath) {
48
+ mkdirSync(dirname(outputPath), { recursive: true });
46
49
  writeFileSync(outputPath, JSON.stringify(payload, null, 2), 'utf-8');
47
50
  }
48
51
  export function getDefaultReportPath(cwd) {
49
52
  const date = new Date().toISOString().split('T')[0];
50
- return `${cwd}/codemie-analytics-${date}.html`;
53
+ return join(cwd, `codemie-analytics-${date}.html`);
51
54
  }
52
55
  export function getDefaultReportJsonPath(cwd) {
53
56
  const date = new Date().toISOString().split('T')[0];
54
57
  // `.report.json` (not `.json`) so the default never collides with `--export json`,
55
58
  // which writes the cost-less analytics tree to `codemie-analytics-<date>.json`.
56
- return `${cwd}/codemie-analytics-${date}.report.json`;
59
+ return join(cwd, `codemie-analytics-${date}.report.json`);
60
+ }
61
+ /**
62
+ * Permission / read-only fs errors that a *different output directory* can resolve.
63
+ * Seen when the report defaults to a cwd that is a drive root (Windows `D:\`) or a
64
+ * read-only / write-protected volume (removable, network, BitLocker-locked, etc.).
65
+ */
66
+ export function isUnwritableLocationError(err) {
67
+ const code = err?.code;
68
+ return code === 'EPERM' || code === 'EACCES' || code === 'EROFS';
69
+ }
70
+ /**
71
+ * Writes a report via `write(path)`. If the preferred location is unwritable
72
+ * (drive root, read-only volume) AND `allowFallback` is true, retries the same
73
+ * filename under the user's home dir, then the OS temp dir, and reports where it
74
+ * landed. With `allowFallback` false (an explicit `--report-output`) or for any
75
+ * non-permission error, the original error propagates unchanged.
76
+ */
77
+ export function writeReportWithFallback(write, preferredPath, allowFallback) {
78
+ try {
79
+ write(preferredPath);
80
+ return { path: preferredPath };
81
+ }
82
+ catch (err) {
83
+ if (!allowFallback || !isUnwritableLocationError(err))
84
+ throw err;
85
+ const name = basename(preferredPath);
86
+ for (const dir of [homedir(), tmpdir()]) {
87
+ const candidate = join(dir, name);
88
+ if (candidate === preferredPath)
89
+ continue;
90
+ try {
91
+ write(candidate);
92
+ return { path: candidate, relocatedFrom: preferredPath };
93
+ }
94
+ catch (inner) {
95
+ if (!isUnwritableLocationError(inner))
96
+ throw inner;
97
+ }
98
+ }
99
+ throw err;
100
+ }
57
101
  }
58
102
  //# sourceMappingURL=report-generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"report-generator.js","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/report/report-generator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAGxD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,uCAAuC;AAEjF,uDAAuD;AACvD,MAAM,UAAU,gBAAgB,CAAC,KAMhC;IACC,6EAA6E;IAC7E,wFAAwF;IACxF,yFAAyF;IACzF,wFAAwF;IACxF,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACxE,iFAAiF;IACjF,qFAAqF;IACrF,6FAA6F;IAC7F,0FAA0F;IAC1F,6FAA6F;IAC7F,OAAO,KAAK,CAAC,QAAQ;SAClB,OAAO,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC;SACjD,OAAO,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;SACvD,OAAO,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;QACtD,yEAAyE;QACzE,uFAAuF;SACtF,OAAO,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;AAC5D,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,cAAc,CAAC,OAAsB,EAAE,UAAkB;IACvE,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,OAAO,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,gBAAgB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC7E,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAsB,EAAE,UAAkB;IAC3E,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,GAAG,GAAG,sBAAsB,IAAI,OAAO,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,GAAW;IAClD,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,mFAAmF;IACnF,gFAAgF;IAChF,OAAO,GAAG,GAAG,sBAAsB,IAAI,cAAc,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"report-generator.js","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/report/report-generator.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemieai/code",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Unified AI coding assistant CLI - Manage Claude Code, Gemini & custom agents. Multi-provider support (OpenAI, Azure, LiteLLM, SSO). Built-in LangGraph agent with file operations & git integration.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",