@bonginkan/maria-lite 6.3.1 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- MARIA-LITE (v6.3.1)
1
+ MARIA-LITE (v7.0.0)
2
2
  ===================
3
3
 
4
4
  MARIA-LITE is a lightweight, standalone CLI build of MARIA OS focused on a smaller runtime surface while preserving API compatibility with `@bonginkan/maria`.
@@ -43,7 +43,7 @@ Notes:
43
43
  - Clone commands write under `artifacts/<role>-clone/` when `--apply` (or implicit apply is enabled).
44
44
 
45
45
  ## Version
46
- This package is published as `6.3.1`.
46
+ This package is published as `7.0.0`.
47
47
 
48
48
  ## Extensions (Enterprise)
49
49
 
@@ -126,6 +126,33 @@ Append creator-provided knowledge to common context:
126
126
 
127
127
  ## Release Notes
128
128
 
129
+ ### v7.0.0 (2026/03)
130
+
131
+ #### Features
132
+
133
+ - /vup now also bumps desktop build metadata for app/exe releases.
134
+ - /vup output includes clearer post-apply steps to commit, tag, and push.
135
+
136
+ #### Bug fixes
137
+
138
+ - Updated bundled knowledge pack catalogs to reflect new and rebalanced entries.
139
+
140
+ ---
141
+
142
+ ### v6.3.2 (2026/03)
143
+
144
+ #### Features
145
+
146
+ - Improved /gcal Admin resource management (buildings & rooms) output and handling.
147
+ - Enhanced /resource-manager with clearer tables and create flows for buildings/resources.
148
+
149
+ #### Bug fixes
150
+
151
+ - More consistent Google Admin API error reporting across /gcal and /resource-manager.
152
+ - Improved floor parsing for building creation (numeric counts or comma-separated).
153
+
154
+ ---
155
+
129
156
  ### v6.3.1 (2026/03)
130
157
 
131
158
  #### Features
package/dist/cli.cjs CHANGED
@@ -97578,7 +97578,7 @@ function resolvePackageJsonNearEntrypoint() {
97578
97578
  }
97579
97579
  function resolveMariaLiteVersionInfo() {
97580
97580
  const fallbackName = EXPECTED_PKG_NAME;
97581
- const fallbackVersion = String(process.env.MARIA_LITE_VERSION || "").trim() || "6.3.1";
97581
+ const fallbackVersion = String(process.env.MARIA_LITE_VERSION || "").trim() || "7.0.0";
97582
97582
  const near = resolvePackageJsonNearEntrypoint();
97583
97583
  if (near) {
97584
97584
  const name = fallbackName;
@@ -101169,6 +101169,7 @@ This command requires the repo scripts.` };
101169
101169
  lines.push(entryPreview);
101170
101170
  lines.push("");
101171
101171
  lines.push("Tip: run with --apply to write changes.");
101172
+ lines.push("After --apply, commit + tag + push to trigger Tauri desktop build.");
101172
101173
  return {
101173
101174
  text: lines.join("\n").trim(),
101174
101175
  json: wantsJson ? {
@@ -101211,8 +101212,13 @@ This command requires the repo scripts.` };
101211
101212
  if (nextDataVersion) outLines.push(`nextData=${nextDataVersion}`);
101212
101213
  outLines.push(`npmLatest=${npmLatest}`);
101213
101214
  outLines.push(`npmGitHead=${baseSha}`);
101214
- const updatedFiles = ["src-lite/package.json", "src-lite/package-lock.json", "src-lite/shared/version.ts", "src-lite/README.md", "src-lite/maria-lite-data/package.json"];
101215
+ const updatedFiles = ["src-lite/package.json", "src-lite/package-lock.json", "src-lite/shared/version.ts", "src-lite/README.md", "src-lite/maria-lite-data/package.json", "src-lite/src-tauri/tauri.conf.json", "src-lite/src-tauri/Cargo.toml"];
101215
101216
  outLines.push(`updated=${updatedFiles.join(", ")}`);
101217
+ outLines.push("");
101218
+ outLines.push("Next steps:");
101219
+ outLines.push(` git add -A && git commit -m "v${nextVersion}"`);
101220
+ outLines.push(` git tag v${nextVersion}`);
101221
+ outLines.push(` git push && git push --tags # \u2192 triggers Tauri desktop build`);
101216
101222
  return {
101217
101223
  text: outLines.join("\n").trim(),
101218
101224
  json: wantsJson ? {
@@ -256284,6 +256290,161 @@ var init_phone_routes = __esm({
256284
256290
  }
256285
256291
  });
256286
256292
 
256293
+ // services/google/admin-resources.ts
256294
+ async function adminFetch(token, url, init) {
256295
+ const headers = {
256296
+ Authorization: `Bearer ${token}`,
256297
+ ...init?.headers || {}
256298
+ };
256299
+ return fetch(url, { ...init, headers });
256300
+ }
256301
+ function slugify2(name, prefix) {
256302
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `${prefix}-${Date.now()}`;
256303
+ }
256304
+ function parseFloorNames(raw) {
256305
+ const trimmed = raw.trim();
256306
+ if (!trimmed) return [];
256307
+ const n = Number(trimmed);
256308
+ if (!isNaN(n) && n > 0 && Number.isInteger(n)) {
256309
+ return Array.from({ length: n }, (_, i2) => String(i2 + 1));
256310
+ }
256311
+ return trimmed.split(",").map((f3) => f3.trim()).filter(Boolean);
256312
+ }
256313
+ function toBuilding(raw) {
256314
+ return {
256315
+ buildingId: String(raw.buildingId || ""),
256316
+ buildingName: String(raw.buildingName || ""),
256317
+ description: String(raw.description || ""),
256318
+ floorNames: Array.isArray(raw.floorNames) ? raw.floorNames.map(String) : []
256319
+ };
256320
+ }
256321
+ function toResource(raw) {
256322
+ return {
256323
+ resourceId: String(raw.resourceId || ""),
256324
+ resourceEmail: String(raw.resourceEmail || ""),
256325
+ resourceName: String(raw.resourceName || ""),
256326
+ resourceType: String(raw.resourceType || ""),
256327
+ capacity: Number(raw.capacity || 0),
256328
+ buildingId: String(raw.buildingId || ""),
256329
+ floorName: String(raw.floorName || ""),
256330
+ userVisibleDescription: String(raw.userVisibleDescription || ""),
256331
+ resourceDescription: String(raw.resourceDescription || ""),
256332
+ generatedResourceName: String(raw.generatedResourceName || "")
256333
+ };
256334
+ }
256335
+ async function parseErrorText(res) {
256336
+ return res.text().catch(() => "");
256337
+ }
256338
+ function apiError(status, errText) {
256339
+ if (status === 403) return { ok: false, error: "permission_denied", status };
256340
+ if (status === 404) return { ok: false, error: "not_found", status };
256341
+ return { ok: false, error: `Admin SDK: ${status} ${errText.slice(0, 200)}`, status };
256342
+ }
256343
+ async function listBuildingsRaw(token, signal) {
256344
+ const res = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/buildings?maxResults=500`, signal ? { signal } : void 0);
256345
+ if (!res.ok) return apiError(res.status, await parseErrorText(res));
256346
+ const data = await res.json();
256347
+ const items = Array.isArray(data.buildings) ? data.buildings : [];
256348
+ return { ok: true, data: items.map(toBuilding) };
256349
+ }
256350
+ async function createBuildingRaw(token, params, signal) {
256351
+ const buildingId = params.buildingId || slugify2(params.name, "bld");
256352
+ const body = { buildingId, buildingName: params.name };
256353
+ if (params.description) body.description = params.description;
256354
+ if (params.floorNames) {
256355
+ body.floorNames = params.floorNames;
256356
+ } else if (params.floors) {
256357
+ body.floorNames = parseFloorNames(params.floors);
256358
+ }
256359
+ const res = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/buildings`, {
256360
+ method: "POST",
256361
+ headers: { "Content-Type": "application/json" },
256362
+ body: JSON.stringify(body),
256363
+ ...signal ? { signal } : {}
256364
+ });
256365
+ if (!res.ok) return apiError(res.status, await parseErrorText(res));
256366
+ return { ok: true, data: toBuilding(await res.json()) };
256367
+ }
256368
+ async function updateBuildingRaw(token, buildingId, body, signal) {
256369
+ const res = await adminFetch(
256370
+ token,
256371
+ `${ADMIN_RESOURCES_BASE}/buildings/${encodeURIComponent(buildingId)}`,
256372
+ { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), ...signal ? { signal } : {} }
256373
+ );
256374
+ if (!res.ok) return apiError(res.status, await parseErrorText(res));
256375
+ return { ok: true, data: toBuilding(await res.json()) };
256376
+ }
256377
+ async function listResourcesRaw(token, opts, signal) {
256378
+ let url = `${ADMIN_RESOURCES_BASE}/calendars?maxResults=500`;
256379
+ if (opts?.buildingId) {
256380
+ url += `&query=buildingId="${encodeURIComponent(opts.buildingId)}"`;
256381
+ }
256382
+ const res = await adminFetch(token, url, signal ? { signal } : void 0);
256383
+ if (!res.ok) return apiError(res.status, await parseErrorText(res));
256384
+ const data = await res.json();
256385
+ let items = Array.isArray(data.items) ? data.items : [];
256386
+ if (opts?.capacity && opts.capacity > 0) {
256387
+ items = items.filter((r2) => Number(r2.capacity || 0) >= opts.capacity);
256388
+ }
256389
+ return { ok: true, data: items.map(toResource) };
256390
+ }
256391
+ async function getResourceRaw(token, resourceId, signal) {
256392
+ const res = await adminFetch(
256393
+ token,
256394
+ `${ADMIN_RESOURCES_BASE}/calendars/${encodeURIComponent(resourceId)}`,
256395
+ signal ? { signal } : void 0
256396
+ );
256397
+ if (!res.ok) return apiError(res.status, await parseErrorText(res));
256398
+ return { ok: true, data: toResource(await res.json()) };
256399
+ }
256400
+ async function createResourceRaw(token, params, signal) {
256401
+ const body = {
256402
+ resourceName: params.name,
256403
+ resourceType: params.resourceType || "CONFERENCE_ROOM"
256404
+ };
256405
+ if (params.resourceId) body.resourceId = params.resourceId;
256406
+ if (params.buildingId) body.buildingId = params.buildingId;
256407
+ if (params.capacity) body.capacity = params.capacity;
256408
+ if (params.floorName) body.floorName = params.floorName;
256409
+ if (params.description) body.resourceDescription = params.description;
256410
+ const res = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/calendars`, {
256411
+ method: "POST",
256412
+ headers: { "Content-Type": "application/json" },
256413
+ body: JSON.stringify(body),
256414
+ ...signal ? { signal } : {}
256415
+ });
256416
+ if (!res.ok) return apiError(res.status, await parseErrorText(res));
256417
+ return { ok: true, data: toResource(await res.json()) };
256418
+ }
256419
+ async function updateResourceRaw(token, resourceId, body, signal) {
256420
+ const res = await adminFetch(
256421
+ token,
256422
+ `${ADMIN_RESOURCES_BASE}/calendars/${encodeURIComponent(resourceId)}`,
256423
+ { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), ...signal ? { signal } : {} }
256424
+ );
256425
+ if (!res.ok) return apiError(res.status, await parseErrorText(res));
256426
+ return { ok: true, data: toResource(await res.json()) };
256427
+ }
256428
+ async function fetchExistingBuildingIds(token, signal) {
256429
+ const ids = /* @__PURE__ */ new Set();
256430
+ try {
256431
+ const result = await listBuildingsRaw(token, signal);
256432
+ if (result.ok && result.data) {
256433
+ for (const b of result.data) {
256434
+ if (b.buildingId) ids.add(b.buildingId);
256435
+ }
256436
+ }
256437
+ } catch {
256438
+ }
256439
+ return ids;
256440
+ }
256441
+ var ADMIN_RESOURCES_BASE;
256442
+ var init_admin_resources = __esm({
256443
+ "services/google/admin-resources.ts"() {
256444
+ ADMIN_RESOURCES_BASE = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources";
256445
+ }
256446
+ });
256447
+
256287
256448
  // services/desktop/routes/calendar-api-routes.ts
256288
256449
  async function getToken2() {
256289
256450
  const mgr = new GoogleOAuthManager();
@@ -256293,13 +256454,6 @@ function notConnected2(res) {
256293
256454
  respondJson2(res, 200, { ok: false, error: "not_connected" });
256294
256455
  return true;
256295
256456
  }
256296
- async function gFetch2(token, url, init) {
256297
- const headers = {
256298
- Authorization: `Bearer ${token}`,
256299
- ...init?.headers || {}
256300
- };
256301
- return fetch(url, { ...init, headers });
256302
- }
256303
256457
  function resolveProjectId2() {
256304
256458
  return process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT || process.env.FIREBASE_PROJECT_ID || process.env.GCP_PROJECT_ID || "";
256305
256459
  }
@@ -256357,28 +256511,9 @@ function buildRrule(type2, count, until) {
256357
256511
  return rule;
256358
256512
  }
256359
256513
  async function fetchResources(token, buildingId, minCapacity) {
256360
- let url = `${ADMIN_RESOURCES_BASE}/calendars?maxResults=500`;
256361
- if (buildingId) {
256362
- url += `&query=buildingId="${encodeURIComponent(buildingId)}"`;
256363
- }
256364
- const apiRes = await gFetch2(token, url);
256365
- if (!apiRes.ok) return [];
256366
- const data = await apiRes.json();
256367
- const items = Array.isArray(data.items) ? data.items : [];
256368
- const resources = items.map((item) => ({
256369
- resourceId: String(item.resourceId || ""),
256370
- resourceEmail: String(item.resourceEmail || ""),
256371
- resourceName: String(item.resourceName || ""),
256372
- resourceType: String(item.resourceType || ""),
256373
- capacity: Number(item.capacity || 0),
256374
- buildingId: String(item.buildingId || ""),
256375
- floorName: String(item.floorName || ""),
256376
- userVisibleDescription: String(item.userVisibleDescription || "")
256377
- }));
256378
- if (minCapacity != null && minCapacity > 0) {
256379
- return resources.filter((r2) => r2.capacity >= minCapacity);
256380
- }
256381
- return resources;
256514
+ const result = await listResourcesRaw(token, { buildingId, capacity: minCapacity });
256515
+ if (!result.ok || !result.data) return [];
256516
+ return result.data;
256382
256517
  }
256383
256518
  function findSlots(params) {
256384
256519
  const {
@@ -256538,19 +256673,9 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256538
256673
  if (method === "GET" && pathname === "/api/calendar/buildings") {
256539
256674
  const token = await getToken2();
256540
256675
  if (!token) return notConnected2(res);
256541
- const apiRes = await gFetch2(token, `${ADMIN_RESOURCES_BASE}/buildings?maxResults=500`);
256542
- if (!apiRes.ok) {
256543
- return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status}` }), true;
256544
- }
256545
- const data = await apiRes.json();
256546
- const items = Array.isArray(data.buildings) ? data.buildings : [];
256547
- const buildings = items.map((b) => ({
256548
- buildingId: String(b.buildingId || ""),
256549
- buildingName: String(b.buildingName || ""),
256550
- description: String(b.description || ""),
256551
- floorNames: Array.isArray(b.floorNames) ? b.floorNames : []
256552
- }));
256553
- return respondJson2(res, 200, { ok: true, buildings }), true;
256676
+ const result = await listBuildingsRaw(token);
256677
+ if (!result.ok) return respondJson2(res, 200, { ok: false, error: result.error }), true;
256678
+ return respondJson2(res, 200, { ok: true, buildings: result.data }), true;
256554
256679
  }
256555
256680
  if (method === "POST" && pathname === "/api/calendar/buildings") {
256556
256681
  const token = await getToken2();
@@ -256559,44 +256684,21 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256559
256684
  if (!reqBody) return respondJson2(res, 400, { ok: false, error: "Request body is required" }), true;
256560
256685
  const buildingName = String(reqBody.buildingName || "").trim();
256561
256686
  if (!buildingName) return respondJson2(res, 400, { ok: false, error: "buildingName is required" }), true;
256562
- const buildingId = String(reqBody.buildingId || "").trim() || buildingName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `bld-${Date.now()}`;
256563
- const body = { buildingId, buildingName };
256564
- if (reqBody.description) body.description = String(reqBody.description).trim();
256565
- if (reqBody.floorNames) {
256566
- if (Array.isArray(reqBody.floorNames)) {
256567
- body.floorNames = reqBody.floorNames.map(String);
256568
- } else {
256569
- const raw = String(reqBody.floorNames).trim();
256570
- const n = Number(raw);
256571
- if (!isNaN(n) && n > 0 && Number.isInteger(n)) {
256572
- body.floorNames = Array.from({ length: n }, (_, i2) => String(i2 + 1));
256573
- } else {
256574
- body.floorNames = raw.split(",").map((f3) => f3.trim()).filter(Boolean);
256575
- }
256576
- }
256577
- }
256578
- const apiRes = await gFetch2(token, `${ADMIN_RESOURCES_BASE}/buildings`, {
256579
- method: "POST",
256580
- headers: { "Content-Type": "application/json" },
256581
- body: JSON.stringify(body)
256687
+ const buildingId = String(reqBody.buildingId || "").trim() || slugify2(buildingName, "bld");
256688
+ const floorNames = reqBody.floorNames ? Array.isArray(reqBody.floorNames) ? reqBody.floorNames.map(String) : void 0 : void 0;
256689
+ const floors = !floorNames && reqBody.floorNames ? String(reqBody.floorNames).trim() : void 0;
256690
+ const result = await createBuildingRaw(token, {
256691
+ name: buildingName,
256692
+ buildingId,
256693
+ description: reqBody.description ? String(reqBody.description).trim() : void 0,
256694
+ floorNames: floorNames || void 0,
256695
+ floors: floors || void 0
256582
256696
  });
256583
- if (!apiRes.ok) {
256584
- const errText = await apiRes.text().catch(() => "");
256585
- if (apiRes.status === 403) {
256586
- return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
256587
- }
256588
- return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status} ${errText}` }), true;
256697
+ if (!result.ok) {
256698
+ if (result.status === 403) return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
256699
+ return respondJson2(res, 200, { ok: false, error: result.error }), true;
256589
256700
  }
256590
- const created = await apiRes.json();
256591
- return respondJson2(res, 200, {
256592
- ok: true,
256593
- building: {
256594
- buildingId: String(created.buildingId || ""),
256595
- buildingName: String(created.buildingName || ""),
256596
- description: String(created.description || ""),
256597
- floorNames: Array.isArray(created.floorNames) ? created.floorNames : []
256598
- }
256599
- }), true;
256701
+ return respondJson2(res, 200, { ok: true, building: result.data }), true;
256600
256702
  }
256601
256703
  if (method === "POST" && pathname === "/api/calendar/resources") {
256602
256704
  const token = await getToken2();
@@ -256605,41 +256707,21 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256605
256707
  if (!reqBody) return respondJson2(res, 400, { ok: false, error: "Request body is required" }), true;
256606
256708
  const resourceName = String(reqBody.resourceName || "").trim();
256607
256709
  if (!resourceName) return respondJson2(res, 400, { ok: false, error: "resourceName is required" }), true;
256608
- const resourceId = String(reqBody.resourceId || "").trim() || resourceName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `res-${Date.now()}`;
256609
- const body = {
256710
+ const resourceId = String(reqBody.resourceId || "").trim() || slugify2(resourceName, "res");
256711
+ const result = await createResourceRaw(token, {
256712
+ name: resourceName,
256610
256713
  resourceId,
256611
- resourceName,
256612
- resourceType: String(reqBody.resourceType || "CONFERENCE_ROOM").trim()
256613
- };
256614
- if (reqBody.buildingId) body.buildingId = String(reqBody.buildingId).trim();
256615
- if (reqBody.capacity) body.capacity = Math.max(0, Number(reqBody.capacity) || 0);
256616
- if (reqBody.floorName) body.floorName = String(reqBody.floorName).trim();
256617
- if (reqBody.resourceDescription) body.resourceDescription = String(reqBody.resourceDescription).trim();
256618
- const apiRes = await gFetch2(token, `${ADMIN_RESOURCES_BASE}/calendars`, {
256619
- method: "POST",
256620
- headers: { "Content-Type": "application/json" },
256621
- body: JSON.stringify(body)
256714
+ buildingId: reqBody.buildingId ? String(reqBody.buildingId).trim() : void 0,
256715
+ capacity: reqBody.capacity ? Math.max(0, Number(reqBody.capacity) || 0) : void 0,
256716
+ resourceType: String(reqBody.resourceType || "CONFERENCE_ROOM").trim(),
256717
+ floorName: reqBody.floorName ? String(reqBody.floorName).trim() : void 0,
256718
+ description: reqBody.resourceDescription ? String(reqBody.resourceDescription).trim() : void 0
256622
256719
  });
256623
- if (!apiRes.ok) {
256624
- const errText = await apiRes.text().catch(() => "");
256625
- if (apiRes.status === 403) {
256626
- return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
256627
- }
256628
- return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status} ${errText}` }), true;
256720
+ if (!result.ok) {
256721
+ if (result.status === 403) return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
256722
+ return respondJson2(res, 200, { ok: false, error: result.error }), true;
256629
256723
  }
256630
- const created = await apiRes.json();
256631
- return respondJson2(res, 200, {
256632
- ok: true,
256633
- resource: {
256634
- resourceId: String(created.resourceId || ""),
256635
- resourceEmail: String(created.resourceEmail || ""),
256636
- resourceName: String(created.resourceName || ""),
256637
- capacity: Number(created.capacity || 0),
256638
- buildingId: String(created.buildingId || ""),
256639
- resourceType: String(created.resourceType || ""),
256640
- floorName: String(created.floorName || "")
256641
- }
256642
- }), true;
256724
+ return respondJson2(res, 200, { ok: true, resource: result.data }), true;
256643
256725
  }
256644
256726
  if (method === "PATCH" && pathname.startsWith("/api/calendar/buildings/")) {
256645
256727
  const buildingId = decodeURIComponent(pathname.slice("/api/calendar/buildings/".length));
@@ -256667,31 +256749,13 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256667
256749
  if (Object.keys(body).length === 0) {
256668
256750
  return respondJson2(res, 400, { ok: false, error: "No fields to update" }), true;
256669
256751
  }
256670
- const apiRes = await gFetch2(token, `${ADMIN_RESOURCES_BASE}/buildings/${encodeURIComponent(buildingId)}`, {
256671
- method: "PATCH",
256672
- headers: { "Content-Type": "application/json" },
256673
- body: JSON.stringify(body)
256674
- });
256675
- if (!apiRes.ok) {
256676
- const errText = await apiRes.text().catch(() => "");
256677
- if (apiRes.status === 403) {
256678
- return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
256679
- }
256680
- if (apiRes.status === 404) {
256681
- return respondJson2(res, 404, { ok: false, error: "Building not found" }), true;
256682
- }
256683
- return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status} ${errText}` }), true;
256752
+ const result = await updateBuildingRaw(token, buildingId, body);
256753
+ if (!result.ok) {
256754
+ if (result.status === 403) return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
256755
+ if (result.status === 404) return respondJson2(res, 404, { ok: false, error: "Building not found" }), true;
256756
+ return respondJson2(res, 200, { ok: false, error: result.error }), true;
256684
256757
  }
256685
- const updated = await apiRes.json();
256686
- return respondJson2(res, 200, {
256687
- ok: true,
256688
- building: {
256689
- buildingId: String(updated.buildingId || ""),
256690
- buildingName: String(updated.buildingName || ""),
256691
- description: String(updated.description || ""),
256692
- floorNames: Array.isArray(updated.floorNames) ? updated.floorNames : []
256693
- }
256694
- }), true;
256758
+ return respondJson2(res, 200, { ok: true, building: result.data }), true;
256695
256759
  }
256696
256760
  if (method === "PATCH" && pathname.startsWith("/api/calendar/resources/")) {
256697
256761
  const resourceId = decodeURIComponent(pathname.slice("/api/calendar/resources/".length));
@@ -256710,34 +256774,13 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256710
256774
  if (Object.keys(body).length === 0) {
256711
256775
  return respondJson2(res, 400, { ok: false, error: "No fields to update" }), true;
256712
256776
  }
256713
- const apiRes = await gFetch2(token, `${ADMIN_RESOURCES_BASE}/calendars/${encodeURIComponent(resourceId)}`, {
256714
- method: "PATCH",
256715
- headers: { "Content-Type": "application/json" },
256716
- body: JSON.stringify(body)
256717
- });
256718
- if (!apiRes.ok) {
256719
- const errText = await apiRes.text().catch(() => "");
256720
- if (apiRes.status === 403) {
256721
- return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
256722
- }
256723
- if (apiRes.status === 404) {
256724
- return respondJson2(res, 404, { ok: false, error: "Resource not found" }), true;
256725
- }
256726
- return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status} ${errText}` }), true;
256777
+ const result = await updateResourceRaw(token, resourceId, body);
256778
+ if (!result.ok) {
256779
+ if (result.status === 403) return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
256780
+ if (result.status === 404) return respondJson2(res, 404, { ok: false, error: "Resource not found" }), true;
256781
+ return respondJson2(res, 200, { ok: false, error: result.error }), true;
256727
256782
  }
256728
- const updated = await apiRes.json();
256729
- return respondJson2(res, 200, {
256730
- ok: true,
256731
- resource: {
256732
- resourceId: String(updated.resourceId || ""),
256733
- resourceEmail: String(updated.resourceEmail || ""),
256734
- resourceName: String(updated.resourceName || ""),
256735
- capacity: Number(updated.capacity || 0),
256736
- buildingId: String(updated.buildingId || ""),
256737
- resourceType: String(updated.resourceType || ""),
256738
- floorName: String(updated.floorName || "")
256739
- }
256740
- }), true;
256783
+ return respondJson2(res, 200, { ok: true, resource: result.data }), true;
256741
256784
  }
256742
256785
  if (method === "POST" && pathname === "/api/calendar/slots") {
256743
256786
  const token = await getToken2();
@@ -256788,7 +256831,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256788
256831
  timeZone: tz,
256789
256832
  items: allTargets.map((e2) => ({ id: e2 }))
256790
256833
  };
256791
- const fbRes = await gFetch2(token, `${CALENDAR_API_BASE}/freeBusy`, {
256834
+ const fbRes = await adminFetch(token, `${CALENDAR_API_BASE}/freeBusy`, {
256792
256835
  method: "POST",
256793
256836
  headers: { "Content-Type": "application/json" },
256794
256837
  body: JSON.stringify(fbBody)
@@ -256864,7 +256907,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256864
256907
  timeZone: tz,
256865
256908
  items: targets.map((e2) => ({ id: e2 }))
256866
256909
  };
256867
- const fbRes = await gFetch2(token, `${CALENDAR_API_BASE}/freeBusy`, {
256910
+ const fbRes = await adminFetch(token, `${CALENDAR_API_BASE}/freeBusy`, {
256868
256911
  method: "POST",
256869
256912
  headers: { "Content-Type": "application/json" },
256870
256913
  body: JSON.stringify(fbBody)
@@ -256926,7 +256969,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256926
256969
  timeZone: DEFAULT_TIMEZONE,
256927
256970
  items: [{ id: calendarId }]
256928
256971
  };
256929
- const fbRes = await gFetch2(token, `${CALENDAR_API_BASE}/freeBusy`, {
256972
+ const fbRes = await adminFetch(token, `${CALENDAR_API_BASE}/freeBusy`, {
256930
256973
  method: "POST",
256931
256974
  headers: { "Content-Type": "application/json" },
256932
256975
  body: JSON.stringify(fbBody)
@@ -256968,7 +257011,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
256968
257011
  if (rrule) {
256969
257012
  eventBody.recurrence = [rrule];
256970
257013
  }
256971
- const createRes = await gFetch2(
257014
+ const createRes = await adminFetch(
256972
257015
  token,
256973
257016
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events`,
256974
257017
  {
@@ -257043,7 +257086,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257043
257086
  const msg = err instanceof Error ? err.message : String(err);
257044
257087
  if (calendarEventId) {
257045
257088
  try {
257046
- await gFetch2(
257089
+ await adminFetch(
257047
257090
  token,
257048
257091
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`,
257049
257092
  { method: "DELETE" }
@@ -257100,7 +257143,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257100
257143
  if (!token) return notConnected2(res);
257101
257144
  const calendarId = String(data.resourceCalendarId || "") || "primary";
257102
257145
  const eventId = String(data.calendarEventId);
257103
- const instancesRes = await gFetch2(
257146
+ const instancesRes = await adminFetch(
257104
257147
  token,
257105
257148
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}/instances?maxResults=50`
257106
257149
  );
@@ -257150,7 +257193,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257150
257193
  }
257151
257194
  const upsertToken = await getToken2();
257152
257195
  if (!upsertToken) return notConnected2(res);
257153
- const eventRes = await gFetch2(
257196
+ const eventRes = await adminFetch(
257154
257197
  upsertToken,
257155
257198
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarIdForUpsert)}/events/${encodeURIComponent(gcalEventId)}`
257156
257199
  );
@@ -257203,7 +257246,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257203
257246
  timeZone: DEFAULT_TIMEZONE,
257204
257247
  items: [{ id: calendarId }]
257205
257248
  };
257206
- const fbRes = await gFetch2(token, `${CALENDAR_API_BASE}/freeBusy`, {
257249
+ const fbRes = await adminFetch(token, `${CALENDAR_API_BASE}/freeBusy`, {
257207
257250
  method: "POST",
257208
257251
  headers: { "Content-Type": "application/json" },
257209
257252
  body: JSON.stringify(fbBody)
@@ -257250,7 +257293,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257250
257293
  if (resourceEmail && resourceEmail !== String(data.resourceCalendarId || "")) {
257251
257294
  patchBody.attendees = [{ email: resourceEmail, resource: true }];
257252
257295
  }
257253
- const patchRes = await gFetch2(
257296
+ const patchRes = await adminFetch(
257254
257297
  token,
257255
257298
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`,
257256
257299
  { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(patchBody) }
@@ -257303,7 +257346,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257303
257346
  }
257304
257347
  const upsertToken = await getToken2();
257305
257348
  if (!upsertToken) return notConnected2(res);
257306
- const eventRes = await gFetch2(
257349
+ const eventRes = await adminFetch(
257307
257350
  upsertToken,
257308
257351
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(gcalCalendarId)}/events/${encodeURIComponent(gcalEventId)}`
257309
257352
  );
@@ -257355,7 +257398,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257355
257398
  }
257356
257399
  if (token) {
257357
257400
  try {
257358
- await gFetch2(
257401
+ await adminFetch(
257359
257402
  token,
257360
257403
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(instanceEventId)}`,
257361
257404
  { method: "DELETE" }
@@ -257379,7 +257422,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257379
257422
  }
257380
257423
  if (token && calendarEventId) {
257381
257424
  try {
257382
- const instanceRes = await gFetch2(
257425
+ const instanceRes = await adminFetch(
257383
257426
  token,
257384
257427
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(instanceEventId)}`
257385
257428
  );
@@ -257390,7 +257433,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257390
257433
  const cutoffDate = new Date(instanceStart);
257391
257434
  cutoffDate.setDate(cutoffDate.getDate() - 1);
257392
257435
  const untilStr = cutoffDate.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z";
257393
- const parentRes = await gFetch2(
257436
+ const parentRes = await adminFetch(
257394
257437
  token,
257395
257438
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`
257396
257439
  );
@@ -257404,7 +257447,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257404
257447
  );
257405
257448
  return [...parts, `UNTIL=${untilStr}`].join(";");
257406
257449
  });
257407
- await gFetch2(
257450
+ await adminFetch(
257408
257451
  token,
257409
257452
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`,
257410
257453
  {
@@ -257436,7 +257479,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257436
257479
  } else {
257437
257480
  if (calendarEventId && token) {
257438
257481
  try {
257439
- await gFetch2(
257482
+ await adminFetch(
257440
257483
  token,
257441
257484
  `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`,
257442
257485
  { method: "DELETE" }
@@ -257581,7 +257624,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257581
257624
  try {
257582
257625
  const calendarFetches = Array.from(byCalendar.keys()).map(async (calendarId) => {
257583
257626
  const eventsUrl = `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events?timeMin=${encodeURIComponent(timeMin)}&timeMax=${encodeURIComponent(timeMax)}&singleEvents=true&orderBy=startTime&maxResults=250`;
257584
- const eventsRes = await gFetch2(token, eventsUrl);
257627
+ const eventsRes = await adminFetch(token, eventsUrl);
257585
257628
  if (!eventsRes.ok) {
257586
257629
  console.warn(
257587
257630
  `GCal events.list failed for calendar ${calendarId}: ${eventsRes.status}`
@@ -257748,13 +257791,13 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
257748
257791
  }
257749
257792
  return false;
257750
257793
  }
257751
- var ADMIN_RESOURCES_BASE, CALENDAR_API_BASE, DEFAULT_WORK_START_HOUR, DEFAULT_WORK_END_HOUR, DEFAULT_DURATION_MINUTES, DEFAULT_RESERVATION_LIMIT, SLOT_STEP_MS, DEFAULT_BUFFER_MINUTES, TOP_SLOT_COUNT, DEFAULT_TIMEZONE, _firestoreInstance2, _firestoreInitPromise2, VALID_RECURRENCE_TYPES;
257794
+ var CALENDAR_API_BASE, DEFAULT_WORK_START_HOUR, DEFAULT_WORK_END_HOUR, DEFAULT_DURATION_MINUTES, DEFAULT_RESERVATION_LIMIT, SLOT_STEP_MS, DEFAULT_BUFFER_MINUTES, TOP_SLOT_COUNT, DEFAULT_TIMEZONE, _firestoreInstance2, _firestoreInitPromise2, VALID_RECURRENCE_TYPES;
257752
257795
  var init_calendar_api_routes = __esm({
257753
257796
  "services/desktop/routes/calendar-api-routes.ts"() {
257754
257797
  init_desktop_server_helpers();
257755
257798
  init_google_oauth();
257756
257799
  init_date_tz();
257757
- ADMIN_RESOURCES_BASE = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources";
257800
+ init_admin_resources();
257758
257801
  CALENDAR_API_BASE = "https://www.googleapis.com/calendar/v3";
257759
257802
  DEFAULT_WORK_START_HOUR = 9;
257760
257803
  DEFAULT_WORK_END_HOUR = 18;
@@ -263703,12 +263746,8 @@ async function findMeetingSlots(token, required, optional, durationMin, dateFrom
263703
263746
  if (extra?.resourceId) {
263704
263747
  resourceCalendarIds = [extra.resourceId];
263705
263748
  try {
263706
- const adminBaseUrl = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources/calendars";
263707
263749
  const qParams = new URLSearchParams({ maxResults: "5", query: `resourceEmail="${extra.resourceId}"` });
263708
- const rRes = await fetch(`${adminBaseUrl}?${qParams}`, {
263709
- headers: { Authorization: `Bearer ${token}` },
263710
- ...signal ? { signal } : {}
263711
- });
263750
+ const rRes = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/calendars?${qParams}`, signal ? { signal } : void 0);
263712
263751
  if (rRes.ok) {
263713
263752
  const rData = await rRes.json();
263714
263753
  const items = Array.isArray(rData.items) ? rData.items : [];
@@ -263722,25 +263761,12 @@ async function findMeetingSlots(token, required, optional, durationMin, dateFrom
263722
263761
  }
263723
263762
  } else if (extra?.buildingId || extra?.capacity) {
263724
263763
  try {
263725
- const adminBaseUrl = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources/calendars";
263726
- const params = new URLSearchParams({ maxResults: "200" });
263727
- if (extra?.buildingId) params.set("query", `buildingId="${extra.buildingId}"`);
263728
- const rRes = await fetch(`${adminBaseUrl}?${params}`, {
263729
- headers: { Authorization: `Bearer ${token}` },
263730
- ...signal ? { signal } : {}
263731
- });
263732
- if (rRes.ok) {
263733
- const rData = await rRes.json();
263734
- const items = Array.isArray(rData.items) ? rData.items : [];
263735
- const filtered = items.filter((r2) => {
263736
- if (extra?.capacity && typeof r2.capacity === "number" && r2.capacity < extra.capacity) return false;
263737
- return true;
263738
- });
263739
- resourceCalendarIds = filtered.map((r2) => String(r2.resourceEmail || "")).filter(Boolean);
263740
- for (const r2 of items) {
263741
- const email = String(r2.resourceEmail || "");
263742
- const name = String(r2.resourceName || r2.generatedResourceName || "");
263743
- if (email && name) resourceNameMap[email] = name;
263764
+ const result = await listResourcesRaw(token, { buildingId: extra?.buildingId, capacity: extra?.capacity }, signal);
263765
+ if (result.ok && result.data) {
263766
+ resourceCalendarIds = result.data.map((r2) => r2.resourceEmail).filter(Boolean);
263767
+ for (const r2 of result.data) {
263768
+ const name = r2.resourceName || r2.generatedResourceName || "";
263769
+ if (r2.resourceEmail && name) resourceNameMap[r2.resourceEmail] = name;
263744
263770
  }
263745
263771
  }
263746
263772
  } catch {
@@ -264122,46 +264148,17 @@ function formatImportSummary(results, totalRecords, isDryRun) {
264122
264148
  }
264123
264149
  return lines;
264124
264150
  }
264125
- async function fetchExistingBuildingIds(token, signal) {
264126
- const ids = /* @__PURE__ */ new Set();
264127
- try {
264128
- const res = await fetch(`${ADMIN_RESOURCES_BASE2}/buildings?maxResults=200`, {
264129
- headers: { Authorization: `Bearer ${token}` },
264130
- ...signal ? { signal } : {}
264131
- });
264132
- if (res.ok) {
264133
- const data = await res.json();
264134
- const buildings = Array.isArray(data.buildings) ? data.buildings : [];
264135
- for (const b of buildings) {
264136
- if (typeof b.buildingId === "string" && b.buildingId) {
264137
- ids.add(b.buildingId);
264138
- }
264139
- }
264140
- }
264141
- } catch {
264142
- }
264143
- return ids;
264144
- }
264145
- async function listResources(token, buildingId, signal) {
264146
- const params = new URLSearchParams({ maxResults: "200" });
264147
- if (buildingId) params.set("query", `buildingId="${buildingId}"`);
264148
- const res = await fetch(`${ADMIN_RESOURCES_BASE2}/calendars?${params}`, {
264149
- headers: { Authorization: `Bearer ${token}` },
264150
- ...signal ? { signal } : {}
264151
- });
264152
- if (!res.ok) {
264153
- const err = await res.text().catch(() => "");
264154
- return { text: `Admin API error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
264155
- }
264156
- const data = await res.json();
264157
- const items = Array.isArray(data.items) ? data.items : [];
264151
+ async function fmtListResources(token, buildingId, signal) {
264152
+ const result = await listResourcesRaw(token, { buildingId }, signal);
264153
+ if (!result.ok) return { text: `Admin API error: ${result.error}`, json: { ok: false, error: result.error } };
264154
+ const items = result.data;
264158
264155
  if (items.length === 0) {
264159
264156
  const filter = buildingId ? ` (building: ${buildingId})` : "";
264160
264157
  return { text: `No resource calendars found${filter}.`, json: { ok: true, resources: [] } };
264161
264158
  }
264162
264159
  const lines = [`${items.length} resource calendar(s):`, ""];
264163
264160
  for (const r2 of items) {
264164
- const cap = typeof r2.capacity === "number" ? ` (capacity: ${r2.capacity})` : "";
264161
+ const cap = r2.capacity ? ` (capacity: ${r2.capacity})` : "";
264165
264162
  const bld = r2.buildingId ? ` [building: ${r2.buildingId}]` : "";
264166
264163
  lines.push(` ${r2.resourceName || r2.generatedResourceName || "Unnamed"}${cap}${bld}`);
264167
264164
  lines.push(` ID: ${r2.resourceId}`);
@@ -264172,22 +264169,16 @@ async function listResources(token, buildingId, signal) {
264172
264169
  }
264173
264170
  return { text: lines.join("\n"), json: { ok: true, resources: items } };
264174
264171
  }
264175
- async function getResource(token, resourceId, signal) {
264176
- const res = await fetch(`${ADMIN_RESOURCES_BASE2}/calendars/${encodeURIComponent(resourceId)}`, {
264177
- headers: { Authorization: `Bearer ${token}` },
264178
- ...signal ? { signal } : {}
264179
- });
264180
- if (!res.ok) {
264181
- const err = await res.text().catch(() => "");
264182
- return { text: `Admin API error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
264183
- }
264184
- const r2 = await res.json();
264172
+ async function fmtGetResource(token, resourceId, signal) {
264173
+ const result = await getResourceRaw(token, resourceId, signal);
264174
+ if (!result.ok) return { text: `Admin API error: ${result.error}`, json: { ok: false, error: result.error } };
264175
+ const r2 = result.data;
264185
264176
  const lines = [
264186
264177
  `Resource: ${r2.resourceName || r2.generatedResourceName || "Unnamed"}`,
264187
264178
  ` ID: ${r2.resourceId}`,
264188
264179
  ` Email: ${r2.resourceEmail || "N/A"}`,
264189
264180
  ` Type: ${r2.resourceType || "N/A"}`,
264190
- typeof r2.capacity === "number" ? ` Capacity: ${r2.capacity}` : "",
264181
+ r2.capacity ? ` Capacity: ${r2.capacity}` : "",
264191
264182
  r2.buildingId ? ` Building: ${r2.buildingId}` : "",
264192
264183
  r2.floorName ? ` Floor: ${r2.floorName}` : "",
264193
264184
  r2.resourceDescription ? ` Description: ${r2.resourceDescription}` : "",
@@ -264195,26 +264186,10 @@ async function getResource(token, resourceId, signal) {
264195
264186
  ].filter(Boolean);
264196
264187
  return { text: lines.join("\n"), json: { ok: true, resource: r2 } };
264197
264188
  }
264198
- async function createResource(token, params, signal) {
264199
- const body = {
264200
- resourceName: params.name,
264201
- resourceType: params.resourceType || "CONFERENCE_ROOM"
264202
- };
264203
- if (params.buildingId) body.buildingId = params.buildingId;
264204
- if (params.capacity) body.capacity = params.capacity;
264205
- if (params.floorName) body.floorName = params.floorName;
264206
- if (params.description) body.resourceDescription = params.description;
264207
- const res = await fetch(`${ADMIN_RESOURCES_BASE2}/calendars`, {
264208
- method: "POST",
264209
- headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
264210
- body: JSON.stringify(body),
264211
- ...signal ? { signal } : {}
264212
- });
264213
- if (!res.ok) {
264214
- const err = await res.text().catch(() => "");
264215
- return { text: `Admin API create error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
264216
- }
264217
- const r2 = await res.json();
264189
+ async function fmtCreateResource(token, params, signal) {
264190
+ const result = await createResourceRaw(token, params, signal);
264191
+ if (!result.ok) return { text: `Admin API create error: ${result.error}`, json: { ok: false, error: result.error } };
264192
+ const r2 = result.data;
264218
264193
  return {
264219
264194
  text: `Created resource: "${r2.resourceName}" (id=${r2.resourceId}, email=${r2.resourceEmail})`,
264220
264195
  json: { ok: true, created: true, resource: r2 }
@@ -264295,9 +264270,9 @@ async function bulkImportResources(token, filePath4, signal, dryRun = false) {
264295
264270
  if (rec.floor || rec.floorName) body.floorName = rec.floor || rec.floorName;
264296
264271
  if (rec.description || rec.resourceDescription) body.resourceDescription = rec.description || rec.resourceDescription;
264297
264272
  try {
264298
- const createRes = await fetch(`${ADMIN_RESOURCES_BASE2}/calendars`, {
264273
+ const createRes = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/calendars`, {
264299
264274
  method: "POST",
264300
- headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
264275
+ headers: { "Content-Type": "application/json" },
264301
264276
  body: JSON.stringify(body),
264302
264277
  ...signal ? { signal } : {}
264303
264278
  });
@@ -264325,54 +264300,25 @@ async function bulkImportResources(token, filePath4, signal, dryRun = false) {
264325
264300
  }
264326
264301
  };
264327
264302
  }
264328
- async function listBuildings(token, signal) {
264329
- const res = await fetch(`${ADMIN_RESOURCES_BASE2}/buildings?maxResults=200`, {
264330
- headers: { Authorization: `Bearer ${token}` },
264331
- ...signal ? { signal } : {}
264332
- });
264333
- if (!res.ok) {
264334
- const err = await res.text().catch(() => "");
264335
- return { text: `Admin API error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
264336
- }
264337
- const data = await res.json();
264338
- const buildings = Array.isArray(data.buildings) ? data.buildings : [];
264303
+ async function fmtListBuildings(token, signal) {
264304
+ const result = await listBuildingsRaw(token, signal);
264305
+ if (!result.ok) return { text: `Admin API error: ${result.error}`, json: { ok: false, error: result.error } };
264306
+ const buildings = result.data;
264339
264307
  if (buildings.length === 0) return { text: "No buildings found.", json: { ok: true, buildings: [] } };
264340
264308
  const lines = [`${buildings.length} building(s):`, ""];
264341
264309
  for (const b of buildings) {
264342
264310
  lines.push(` ${b.buildingName || "Unnamed"}`);
264343
264311
  lines.push(` ID: ${b.buildingId}`);
264344
264312
  if (b.description) lines.push(` Description: ${b.description}`);
264345
- if (Array.isArray(b.floorNames) && b.floorNames.length) lines.push(` Floors: ${b.floorNames.join(", ")}`);
264313
+ if (b.floorNames.length) lines.push(` Floors: ${b.floorNames.join(", ")}`);
264346
264314
  lines.push("");
264347
264315
  }
264348
264316
  return { text: lines.join("\n"), json: { ok: true, buildings } };
264349
264317
  }
264350
- async function createBuilding(token, params, signal) {
264351
- const buildingId = params.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `bld-${Date.now()}`;
264352
- const body = {
264353
- buildingId,
264354
- buildingName: params.name
264355
- };
264356
- if (params.description) body.description = params.description;
264357
- if (params.floors) {
264358
- const n = Number(params.floors);
264359
- if (n > 0) {
264360
- body.floorNames = Array.from({ length: n }, (_, i2) => String(i2 + 1));
264361
- } else {
264362
- body.floorNames = params.floors.split(",").map((f3) => f3.trim()).filter(Boolean);
264363
- }
264364
- }
264365
- const res = await fetch(`${ADMIN_RESOURCES_BASE2}/buildings`, {
264366
- method: "POST",
264367
- headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
264368
- body: JSON.stringify(body),
264369
- ...signal ? { signal } : {}
264370
- });
264371
- if (!res.ok) {
264372
- const err = await res.text().catch(() => "");
264373
- return { text: `Admin API create error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
264374
- }
264375
- const b = await res.json();
264318
+ async function fmtCreateBuilding(token, params, signal) {
264319
+ const result = await createBuildingRaw(token, params, signal);
264320
+ if (!result.ok) return { text: `Admin API create error: ${result.error}`, json: { ok: false, error: result.error } };
264321
+ const b = result.data;
264376
264322
  return {
264377
264323
  text: `Created building: "${b.buildingName}" (id=${b.buildingId})`,
264378
264324
  json: { ok: true, created: true, building: b }
@@ -264441,18 +264387,16 @@ async function bulkImportBuildings(token, filePath4, signal, dryRun = false) {
264441
264387
  const rec = records[i2];
264442
264388
  const row = i2 + 2;
264443
264389
  const name = rec.name || rec.buildingName || "";
264444
- const bldId = (rec.id || rec.buildingId || name).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `bld-${Date.now()}`;
264390
+ const bldId = slugify2(rec.id || rec.buildingId || name, "bld");
264445
264391
  const body = { buildingId: bldId, buildingName: name };
264446
264392
  if (rec.description) body.description = rec.description;
264447
264393
  if (rec.floors || rec.floorNames) {
264448
- const f3 = rec.floors || rec.floorNames;
264449
- const n = Number(f3);
264450
- body.floorNames = n > 0 ? Array.from({ length: n }, (_, i22) => String(i22 + 1)) : f3.split(",").map((s2) => s2.trim()).filter(Boolean);
264394
+ body.floorNames = parseFloorNames(rec.floors || rec.floorNames);
264451
264395
  }
264452
264396
  try {
264453
- const createRes = await fetch(`${ADMIN_RESOURCES_BASE2}/buildings`, {
264397
+ const createRes = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/buildings`, {
264454
264398
  method: "POST",
264455
- headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
264399
+ headers: { "Content-Type": "application/json" },
264456
264400
  body: JSON.stringify(body),
264457
264401
  ...signal ? { signal } : {}
264458
264402
  });
@@ -264529,12 +264473,13 @@ async function checkAvailability(token, targets, datetime, durationMinutes, sign
264529
264473
  function createGcalField() {
264530
264474
  return { commandId: "gcal", worker: new GcalWorker(), checker: new AlwaysPassChecker11() };
264531
264475
  }
264532
- var GcalWorker, ADMIN_RESOURCES_BASE2, EMAIL_REGEX, AlwaysPassChecker11;
264476
+ var GcalWorker, EMAIL_REGEX, AlwaysPassChecker11;
264533
264477
  var init_gcal_field = __esm({
264534
264478
  "commands/google/gcal.field.ts"() {
264535
264479
  init_base2();
264536
264480
  init_google_oauth();
264537
264481
  init_date_tz();
264482
+ init_admin_resources();
264538
264483
  GcalWorker = class extends LiteWorkerAgent {
264539
264484
  commandId = "gcal";
264540
264485
  help = {
@@ -264642,17 +264587,17 @@ var init_gcal_field = __esm({
264642
264587
  const resSub = (ctx.parsed.args?.[1] || "list").toLowerCase();
264643
264588
  if (resSub === "list") {
264644
264589
  const buildingId = String(ctx.parsed.options.building || "").trim() || void 0;
264645
- return await listResources(token, buildingId, ctx.abortSignal);
264590
+ return await fmtListResources(token, buildingId, ctx.abortSignal);
264646
264591
  }
264647
264592
  if (resSub === "get") {
264648
264593
  const resourceId = String(ctx.parsed.args?.[2] || ctx.parsed.options.id || "").trim();
264649
264594
  if (!resourceId) return { text: "gcal resources get: resourceId is required" };
264650
- return await getResource(token, resourceId, ctx.abortSignal);
264595
+ return await fmtGetResource(token, resourceId, ctx.abortSignal);
264651
264596
  }
264652
264597
  if (resSub === "create") {
264653
264598
  const name = String(ctx.parsed.options.name || "").trim();
264654
264599
  if (!name) return { text: "gcal resources create: --name is required" };
264655
- return await createResource(token, {
264600
+ return await fmtCreateResource(token, {
264656
264601
  name,
264657
264602
  buildingId: String(ctx.parsed.options.building || "").trim() || void 0,
264658
264603
  capacity: Number(ctx.parsed.options.capacity || "0") || void 0,
@@ -264672,12 +264617,12 @@ var init_gcal_field = __esm({
264672
264617
  if (sub === "buildings") {
264673
264618
  const bldSub = (ctx.parsed.args?.[1] || "list").toLowerCase();
264674
264619
  if (bldSub === "list") {
264675
- return await listBuildings(token, ctx.abortSignal);
264620
+ return await fmtListBuildings(token, ctx.abortSignal);
264676
264621
  }
264677
264622
  if (bldSub === "create") {
264678
264623
  const name = String(ctx.parsed.options.name || "").trim();
264679
264624
  if (!name) return { text: "gcal buildings create: --name is required" };
264680
- return await createBuilding(token, {
264625
+ return await fmtCreateBuilding(token, {
264681
264626
  name,
264682
264627
  floors: String(ctx.parsed.options.floors || "").trim() || void 0,
264683
264628
  description: String(ctx.parsed.options.description || "").trim() || void 0
@@ -264706,7 +264651,6 @@ var init_gcal_field = __esm({
264706
264651
  }
264707
264652
  ];
264708
264653
  };
264709
- ADMIN_RESOURCES_BASE2 = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources";
264710
264654
  EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
264711
264655
  AlwaysPassChecker11 = class extends LiteCheckerAgent {
264712
264656
  commandId = "gcal";
@@ -293291,152 +293235,38 @@ var init_phone_init_field = __esm({
293291
293235
  });
293292
293236
 
293293
293237
  // commands/resource-manager.field.ts
293294
- async function gFetch3(token, url, opts) {
293295
- return fetch(url, {
293296
- ...opts,
293297
- headers: { Authorization: `Bearer ${token}`, ...opts?.headers || {} }
293298
- });
293299
- }
293300
- async function listBuildings2(token, _signal) {
293301
- const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/buildings?maxResults=500`);
293302
- if (!res.ok) {
293303
- return { text: `Resource Manager: Admin SDK error ${res.status}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
293304
- }
293305
- const data = await res.json();
293306
- const items = Array.isArray(data.buildings) ? data.buildings : [];
293307
- if (items.length === 0) {
293308
- return { text: "No buildings found.", json: { ok: true, buildings: [] } };
293309
- }
293238
+ function formatBuildingsTable(items) {
293310
293239
  const lines = ["## Buildings", ""];
293311
293240
  lines.push("| ID | Name | Floors | Description |");
293312
293241
  lines.push("|---|---|---|---|");
293313
293242
  for (const b of items) {
293314
- const floors = Array.isArray(b.floorNames) ? b.floorNames.join(", ") : "";
293315
- lines.push(`| ${b.buildingId || ""} | ${b.buildingName || ""} | ${floors} | ${b.description || ""} |`);
293243
+ const floors = b.floorNames.join(", ");
293244
+ lines.push(`| ${b.buildingId} | ${b.buildingName} | ${floors} | ${b.description} |`);
293316
293245
  }
293317
293246
  lines.push("", `Total: ${items.length} building(s)`);
293318
- return { text: lines.join("\n"), json: { ok: true, buildings: items } };
293247
+ return lines.join("\n");
293319
293248
  }
293320
- async function listResources2(token, buildingId, capacity, _signal) {
293321
- let url = `${ADMIN_RESOURCES_BASE3}/calendars?maxResults=500`;
293322
- const res = await gFetch3(token, url);
293323
- if (!res.ok) {
293324
- return { text: `Resource Manager: Admin SDK error ${res.status}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
293325
- }
293326
- const data = await res.json();
293327
- let items = Array.isArray(data.items) ? data.items : [];
293328
- if (buildingId) items = items.filter((r2) => String(r2.buildingId || "") === buildingId);
293329
- if (capacity) items = items.filter((r2) => Number(r2.capacity || 0) >= capacity);
293330
- if (items.length === 0) {
293331
- return { text: "No resources found.", json: { ok: true, resources: [] } };
293332
- }
293249
+ function formatResourcesTable(items) {
293333
293250
  const lines = ["## Calendar Resources", ""];
293334
293251
  lines.push("| Name | Building | Capacity | Type | Floor | Email |");
293335
293252
  lines.push("|---|---|---|---|---|---|");
293336
293253
  for (const r2 of items) {
293337
- lines.push(`| ${r2.resourceName || ""} | ${r2.buildingId || ""} | ${r2.capacity || ""} | ${r2.resourceType || ""} | ${r2.floorName || ""} | ${r2.resourceEmail || ""} |`);
293254
+ lines.push(`| ${r2.resourceName} | ${r2.buildingId} | ${r2.capacity || ""} | ${r2.resourceType} | ${r2.floorName} | ${r2.resourceEmail} |`);
293338
293255
  }
293339
293256
  lines.push("", `Total: ${items.length} resource(s)`);
293340
- return { text: lines.join("\n"), json: { ok: true, resources: items } };
293341
- }
293342
- async function createBuilding2(token, name, floorsRaw, description, _signal) {
293343
- const buildingId = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `bld-${Date.now()}`;
293344
- const body = { buildingId, buildingName: name };
293345
- if (description) body.description = description;
293346
- if (floorsRaw) {
293347
- const n = Number(floorsRaw);
293348
- if (!isNaN(n) && n > 0 && Number.isInteger(n)) {
293349
- body.floorNames = Array.from({ length: n }, (_, i2) => String(i2 + 1));
293350
- } else {
293351
- body.floorNames = floorsRaw.split(",").map((f3) => f3.trim()).filter(Boolean);
293352
- }
293353
- }
293354
- const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/buildings`, {
293355
- method: "POST",
293356
- headers: { "Content-Type": "application/json" },
293357
- body: JSON.stringify(body)
293358
- });
293359
- if (!res.ok) {
293360
- const errText = await res.text().catch(() => "");
293361
- if (res.status === 403) return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
293362
- return { text: `Failed to create building: ${res.status} ${errText}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
293363
- }
293364
- const created = await res.json();
293365
- return {
293366
- text: `Building created: ${created.buildingName} (${created.buildingId})`,
293367
- json: { ok: true, building: created }
293368
- };
293369
- }
293370
- async function createResource2(token, opts, _signal) {
293371
- const resourceId = opts.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `res-${Date.now()}`;
293372
- const body = { resourceId, resourceName: opts.name, resourceType: opts.resourceType };
293373
- if (opts.buildingId) body.buildingId = opts.buildingId;
293374
- if (opts.capacity) body.capacity = opts.capacity;
293375
- if (opts.floorName) body.floorName = opts.floorName;
293376
- if (opts.description) body.resourceDescription = opts.description;
293377
- const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/calendars`, {
293378
- method: "POST",
293379
- headers: { "Content-Type": "application/json" },
293380
- body: JSON.stringify(body)
293381
- });
293382
- if (!res.ok) {
293383
- const errText = await res.text().catch(() => "");
293384
- if (res.status === 403) return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
293385
- return { text: `Failed to create resource: ${res.status} ${errText}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
293386
- }
293387
- const created = await res.json();
293388
- return {
293389
- text: `Resource created: ${created.resourceName} (${created.resourceEmail})`,
293390
- json: { ok: true, resource: created }
293391
- };
293392
- }
293393
- async function updateBuilding(token, buildingId, body, _signal) {
293394
- const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/buildings/${encodeURIComponent(buildingId)}`, {
293395
- method: "PATCH",
293396
- headers: { "Content-Type": "application/json" },
293397
- body: JSON.stringify(body)
293398
- });
293399
- if (!res.ok) {
293400
- const errText = await res.text().catch(() => "");
293401
- if (res.status === 403) return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
293402
- if (res.status === 404) return { text: `Building "${buildingId}" not found.`, json: { ok: false, error: "not_found" } };
293403
- return { text: `Failed to update building: ${res.status} ${errText}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
293404
- }
293405
- const updated = await res.json();
293406
- return {
293407
- text: `Building updated: ${updated.buildingName} (${updated.buildingId})`,
293408
- json: { ok: true, building: updated }
293409
- };
293410
- }
293411
- async function updateResource(token, resourceId, body, _signal) {
293412
- const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/calendars/${encodeURIComponent(resourceId)}`, {
293413
- method: "PATCH",
293414
- headers: { "Content-Type": "application/json" },
293415
- body: JSON.stringify(body)
293416
- });
293417
- if (!res.ok) {
293418
- const errText = await res.text().catch(() => "");
293419
- if (res.status === 403) return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
293420
- if (res.status === 404) return { text: `Resource "${resourceId}" not found.`, json: { ok: false, error: "not_found" } };
293421
- return { text: `Failed to update resource: ${res.status} ${errText}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
293422
- }
293423
- const updated = await res.json();
293424
- return {
293425
- text: `Resource updated: ${updated.resourceName} (${updated.resourceEmail})`,
293426
- json: { ok: true, resource: updated }
293427
- };
293257
+ return lines.join("\n");
293428
293258
  }
293429
293259
  function createResourceManagerField() {
293430
293260
  const worker = new ResourceManagerWorker();
293431
293261
  const checker = new ResourceManagerChecker();
293432
293262
  return { worker, checker };
293433
293263
  }
293434
- var ADMIN_RESOURCES_BASE3, ResourceManagerWorker, ResourceManagerChecker;
293264
+ var ResourceManagerWorker, ResourceManagerChecker;
293435
293265
  var init_resource_manager_field = __esm({
293436
293266
  "commands/resource-manager.field.ts"() {
293437
293267
  init_base2();
293438
293268
  init_google_oauth();
293439
- ADMIN_RESOURCES_BASE3 = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources";
293269
+ init_admin_resources();
293440
293270
  ResourceManagerWorker = class extends LiteWorkerAgent {
293441
293271
  commandId = "resource-manager";
293442
293272
  help = {
@@ -293460,20 +293290,34 @@ var init_resource_manager_field = __esm({
293460
293290
  }
293461
293291
  const sub = (ctx.parsed.subcommand || ctx.parsed.args?.[0] || "buildings").toLowerCase();
293462
293292
  if (sub === "buildings" || sub === "list-buildings") {
293463
- return await listBuildings2(token, ctx.abortSignal);
293293
+ const result = await listBuildingsRaw(token, ctx.abortSignal);
293294
+ if (!result.ok) return { text: `Resource Manager: ${result.error}`, json: { ok: false, error: result.error } };
293295
+ const items = result.data;
293296
+ if (items.length === 0) return { text: "No buildings found.", json: { ok: true, buildings: [] } };
293297
+ return { text: formatBuildingsTable(items), json: { ok: true, buildings: items } };
293464
293298
  }
293465
293299
  if (sub === "resources" || sub === "list-resources") {
293466
293300
  const buildingId = String(ctx.parsed.options.building || ctx.parsed.options.buildingId || "").trim() || void 0;
293467
293301
  const capacityRaw = String(ctx.parsed.options.capacity || "").trim();
293468
293302
  const capacity = capacityRaw ? Math.max(0, Number(capacityRaw) || 0) : void 0;
293469
- return await listResources2(token, buildingId, capacity, ctx.abortSignal);
293303
+ const result = await listResourcesRaw(token, { buildingId, capacity }, ctx.abortSignal);
293304
+ if (!result.ok) return { text: `Resource Manager: ${result.error}`, json: { ok: false, error: result.error } };
293305
+ const items = result.data;
293306
+ if (items.length === 0) return { text: "No resources found.", json: { ok: true, resources: [] } };
293307
+ return { text: formatResourcesTable(items), json: { ok: true, resources: items } };
293470
293308
  }
293471
293309
  if (sub === "create-building") {
293472
293310
  const name = String(ctx.parsed.options.name || ctx.parsed.prompt || "").trim();
293473
293311
  if (!name) return { text: "resource-manager create-building: --name is required" };
293474
293312
  const floorsRaw = String(ctx.parsed.options.floors || "").trim();
293475
293313
  const description = String(ctx.parsed.options.description || "").trim() || void 0;
293476
- return await createBuilding2(token, name, floorsRaw, description, ctx.abortSignal);
293314
+ const result = await createBuildingRaw(token, { name, floors: floorsRaw || void 0, description }, ctx.abortSignal);
293315
+ if (!result.ok) {
293316
+ if (result.error === "permission_denied") return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
293317
+ return { text: `Failed to create building: ${result.error}`, json: { ok: false, error: result.error } };
293318
+ }
293319
+ const b = result.data;
293320
+ return { text: `Building created: ${b.buildingName} (${b.buildingId})`, json: { ok: true, building: b } };
293477
293321
  }
293478
293322
  if (sub === "create-resource") {
293479
293323
  const name = String(ctx.parsed.options.name || ctx.parsed.prompt || "").trim();
@@ -293483,7 +293327,14 @@ var init_resource_manager_field = __esm({
293483
293327
  const resourceType = String(ctx.parsed.options.type || "CONFERENCE_ROOM").trim();
293484
293328
  const floorName = String(ctx.parsed.options.floor || "").trim() || void 0;
293485
293329
  const description = String(ctx.parsed.options.description || "").trim() || void 0;
293486
- return await createResource2(token, { name, buildingId, capacity, resourceType, floorName, description }, ctx.abortSignal);
293330
+ const resourceId = slugify2(name, "res");
293331
+ const result = await createResourceRaw(token, { name, resourceId, buildingId, capacity, resourceType, floorName, description }, ctx.abortSignal);
293332
+ if (!result.ok) {
293333
+ if (result.error === "permission_denied") return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
293334
+ return { text: `Failed to create resource: ${result.error}`, json: { ok: false, error: result.error } };
293335
+ }
293336
+ const r2 = result.data;
293337
+ return { text: `Resource created: ${r2.resourceName} (${r2.resourceEmail})`, json: { ok: true, resource: r2 } };
293487
293338
  }
293488
293339
  if (sub === "update-building") {
293489
293340
  const id = String(ctx.parsed.options.id || "").trim();
@@ -293492,18 +293343,18 @@ var init_resource_manager_field = __esm({
293492
293343
  const name = String(ctx.parsed.options.name || "").trim();
293493
293344
  if (name) body.buildingName = name;
293494
293345
  const floorsRaw = String(ctx.parsed.options.floors || "").trim();
293495
- if (floorsRaw) {
293496
- const n = Number(floorsRaw);
293497
- if (!isNaN(n) && n > 0 && Number.isInteger(n)) {
293498
- body.floorNames = Array.from({ length: n }, (_, i2) => String(i2 + 1));
293499
- } else {
293500
- body.floorNames = floorsRaw.split(",").map((f3) => f3.trim()).filter(Boolean);
293501
- }
293502
- }
293346
+ if (floorsRaw) body.floorNames = parseFloorNames(floorsRaw);
293503
293347
  const description = String(ctx.parsed.options.description || "").trim();
293504
293348
  if (description) body.description = description;
293505
293349
  if (Object.keys(body).length === 0) return { text: "resource-manager update-building: at least one field to update is required (--name, --floors, --description)" };
293506
- return await updateBuilding(token, id, body, ctx.abortSignal);
293350
+ const result = await updateBuildingRaw(token, id, body, ctx.abortSignal);
293351
+ if (!result.ok) {
293352
+ if (result.error === "permission_denied") return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
293353
+ if (result.error === "not_found") return { text: `Building "${id}" not found.`, json: { ok: false, error: "not_found" } };
293354
+ return { text: `Failed to update building: ${result.error}`, json: { ok: false, error: result.error } };
293355
+ }
293356
+ const b = result.data;
293357
+ return { text: `Building updated: ${b.buildingName} (${b.buildingId})`, json: { ok: true, building: b } };
293507
293358
  }
293508
293359
  if (sub === "update-resource") {
293509
293360
  const id = String(ctx.parsed.options.id || "").trim();
@@ -293522,7 +293373,14 @@ var init_resource_manager_field = __esm({
293522
293373
  const description = String(ctx.parsed.options.description || "").trim();
293523
293374
  if (description) body.resourceDescription = description;
293524
293375
  if (Object.keys(body).length === 0) return { text: "resource-manager update-resource: at least one field to update is required" };
293525
- return await updateResource(token, id, body, ctx.abortSignal);
293376
+ const result = await updateResourceRaw(token, id, body, ctx.abortSignal);
293377
+ if (!result.ok) {
293378
+ if (result.error === "permission_denied") return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
293379
+ if (result.error === "not_found") return { text: `Resource "${id}" not found.`, json: { ok: false, error: "not_found" } };
293380
+ return { text: `Failed to update resource: ${result.error}`, json: { ok: false, error: result.error } };
293381
+ }
293382
+ const r2 = result.data;
293383
+ return { text: `Resource updated: ${r2.resourceName} (${r2.resourceEmail})`, json: { ok: true, resource: r2 } };
293526
293384
  }
293527
293385
  return { text: `resource-manager: unknown subcommand "${sub}". Use buildings, resources, create-building, create-resource, update-building, or update-resource.` };
293528
293386
  }
package/dist/ext.cjs CHANGED
@@ -98004,7 +98004,7 @@ function resolvePackageJsonNearEntrypoint() {
98004
98004
  }
98005
98005
  function resolveMariaLiteVersionInfo() {
98006
98006
  const fallbackName = EXPECTED_PKG_NAME;
98007
- const fallbackVersion = String(process.env.MARIA_LITE_VERSION || "").trim() || "6.3.1";
98007
+ const fallbackVersion = String(process.env.MARIA_LITE_VERSION || "").trim() || "7.0.0";
98008
98008
  const near = resolvePackageJsonNearEntrypoint();
98009
98009
  if (near) {
98010
98010
  const name = fallbackName;
@@ -1 +1 @@
1
- {"buildTimestamp":"2026-03-03T15:59:37.666Z","fileCount":952,"indexJsonlRelPath":"src-lite/origin/index.jsonl","schemaVersion":"maria_lite_origin_index_meta_v1","sourceDir":"src-lite/origin","textExtractedCount":952}
1
+ {"buildTimestamp":"2026-03-03T22:07:03.940Z","fileCount":952,"indexJsonlRelPath":"src-lite/origin/index.jsonl","schemaVersion":"maria_lite_origin_index_meta_v1","sourceDir":"src-lite/origin","textExtractedCount":952}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonginkan/maria-lite",
3
- "version": "6.3.1",
3
+ "version": "7.0.0",
4
4
  "description": "MARIA-LITE: lightweight MARIA OS CLI (src-lite).",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Bonginkan Inc.",