@fml-inc/fml 0.8.11 → 0.8.12
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/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -1
- package/dist/{chunk-2BFFXKUV.js → chunk-Z7MXNJ6X.js} +1 -1
- package/dist/cli.js +43 -32
- package/dist/mcp/server.js +96 -0
- package/dist/observer-server.js +2 -2
- package/dist/pi/extension.js +12204 -5029
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -10,7 +10,8 @@ not install or run a second Panopticon package.
|
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
13
|
-
Node.js 22.
|
|
13
|
+
Node.js 22.23.4+ (22.x), 24.22.1+ (24.x), or 26.12.1+ (26.x), and npm are required.
|
|
14
|
+
These minimum patch versions include the October 2026 Node.js security fixes.
|
|
14
15
|
|
|
15
16
|
On macOS, Linux, and compatible Bash environments, install with:
|
|
16
17
|
|
|
@@ -53,7 +53,7 @@ var PACKAGE_NAME = "@fml-inc/fml";
|
|
|
53
53
|
var UPDATE_TIMEOUT_MS = 12e4;
|
|
54
54
|
var SETUP_TIMEOUT_MS = 3e5;
|
|
55
55
|
function getCurrentVersion() {
|
|
56
|
-
return true ? "0.8.
|
|
56
|
+
return true ? "0.8.12+bc772cee" : "unknown";
|
|
57
57
|
}
|
|
58
58
|
function parseVersion(version) {
|
|
59
59
|
const match = SEMVER_PATTERN.exec(version);
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
execBinSync,
|
|
8
8
|
handleUpdate,
|
|
9
9
|
resolveBin
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-Z7MXNJ6X.js";
|
|
11
11
|
import {
|
|
12
12
|
openObserverLog,
|
|
13
13
|
readJsonFile,
|
|
@@ -132,7 +132,7 @@ var STOP_TIMEOUT_MS = 5e3;
|
|
|
132
132
|
var FORCE_STOP_TIMEOUT_MS = 2e3;
|
|
133
133
|
var POLL_INTERVAL_MS = 50;
|
|
134
134
|
function expectedObserverVersion() {
|
|
135
|
-
return true ? "0.8.
|
|
135
|
+
return true ? "0.8.12+bc772cee" : "dev";
|
|
136
136
|
}
|
|
137
137
|
function delay(ms) {
|
|
138
138
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -3012,12 +3012,27 @@ import path17 from "path";
|
|
|
3012
3012
|
|
|
3013
3013
|
// ../../packages/agent-targets/src/install/hooks/codex.ts
|
|
3014
3014
|
import { createHash as createHash3 } from "crypto";
|
|
3015
|
-
|
|
3015
|
+
|
|
3016
|
+
// ../../packages/agent-targets/src/config-value.ts
|
|
3017
|
+
import { isDeepStrictEqual } from "util";
|
|
3018
|
+
function normalizeRecords(value) {
|
|
3019
|
+
if (Array.isArray(value)) return value.map(normalizeRecords);
|
|
3020
|
+
if (value === null || typeof value !== "object") return value;
|
|
3021
|
+
const prototype = Object.getPrototypeOf(value);
|
|
3022
|
+
if (prototype !== null && prototype !== Object.prototype) return value;
|
|
3023
|
+
return Object.fromEntries(
|
|
3024
|
+
Object.entries(value).map(([key, child]) => [key, normalizeRecords(child)])
|
|
3025
|
+
);
|
|
3026
|
+
}
|
|
3027
|
+
function isConfigValueEqual(left, right) {
|
|
3028
|
+
return isDeepStrictEqual(normalizeRecords(left), normalizeRecords(right));
|
|
3029
|
+
}
|
|
3030
|
+
|
|
3031
|
+
// ../../packages/agent-targets/src/install/hooks/codex.ts
|
|
3016
3032
|
import path14 from "path";
|
|
3017
3033
|
import { parse as parse2 } from "smol-toml";
|
|
3018
3034
|
|
|
3019
3035
|
// ../../packages/agent-targets/src/toml.ts
|
|
3020
|
-
import { isDeepStrictEqual } from "util";
|
|
3021
3036
|
import { parse, stringify } from "smol-toml";
|
|
3022
3037
|
function asRecord2(value) {
|
|
3023
3038
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -3235,7 +3250,7 @@ function updateTomlPaths(source, updated, updates) {
|
|
|
3235
3250
|
"unsupported inline TOML layout; preserving the existing configuration"
|
|
3236
3251
|
);
|
|
3237
3252
|
}
|
|
3238
|
-
if (!
|
|
3253
|
+
if (!isConfigValueEqual(reparsed, updated)) {
|
|
3239
3254
|
throw new Error(
|
|
3240
3255
|
"unsupported inline TOML layout; preserving the existing configuration"
|
|
3241
3256
|
);
|
|
@@ -3801,7 +3816,7 @@ function hasOwn2(record, key) {
|
|
|
3801
3816
|
function changedValuePath(paths, original, updated, key, parentPath) {
|
|
3802
3817
|
const originalHasKey = hasOwn2(original, key);
|
|
3803
3818
|
const updatedHasKey = hasOwn2(updated, key);
|
|
3804
|
-
if (originalHasKey === updatedHasKey && (!originalHasKey ||
|
|
3819
|
+
if (originalHasKey === updatedHasKey && (!originalHasKey || isConfigValueEqual(original[key], updated[key]))) {
|
|
3805
3820
|
return;
|
|
3806
3821
|
}
|
|
3807
3822
|
paths.push([...parentPath, key]);
|
|
@@ -4081,11 +4096,11 @@ function planInstall(context) {
|
|
|
4081
4096
|
}
|
|
4082
4097
|
hooksFile.hooks = hooks;
|
|
4083
4098
|
const mutations = [];
|
|
4084
|
-
if (!
|
|
4099
|
+
if (!isConfigValueEqual(hooksResult.data, hooksFile)) {
|
|
4085
4100
|
const mutation = changedMutation(hooksSnapshot, jsonContents(hooksFile));
|
|
4086
4101
|
if (mutation) mutations.push(mutation);
|
|
4087
4102
|
}
|
|
4088
|
-
if (!
|
|
4103
|
+
if (!isConfigValueEqual(configResult.data, config2)) {
|
|
4089
4104
|
let after;
|
|
4090
4105
|
try {
|
|
4091
4106
|
after = updateCodexConfigToml(
|
|
@@ -4259,7 +4274,7 @@ function planUninstall(context) {
|
|
|
4259
4274
|
const mutation = changedMutation(hooksSnapshot, after);
|
|
4260
4275
|
if (mutation) mutations.push(mutation);
|
|
4261
4276
|
}
|
|
4262
|
-
if (!
|
|
4277
|
+
if (!isConfigValueEqual(configResult.data, config2)) {
|
|
4263
4278
|
let after;
|
|
4264
4279
|
try {
|
|
4265
4280
|
after = updateCodexConfigToml(
|
|
@@ -4302,11 +4317,11 @@ var CODEX_HOOK_INSTALLER = Object.freeze({
|
|
|
4302
4317
|
});
|
|
4303
4318
|
|
|
4304
4319
|
// ../../packages/agent-targets/src/install/hooks/gemini.ts
|
|
4305
|
-
import { isDeepStrictEqual as
|
|
4320
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
4306
4321
|
import path15 from "path";
|
|
4307
4322
|
|
|
4308
4323
|
// ../../packages/agent-targets/src/mcp/jsonc.ts
|
|
4309
|
-
import { isDeepStrictEqual as
|
|
4324
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
4310
4325
|
import {
|
|
4311
4326
|
applyEdits,
|
|
4312
4327
|
modify,
|
|
@@ -4334,7 +4349,7 @@ function longestCommonArraySubsequence(original, updated) {
|
|
|
4334
4349
|
);
|
|
4335
4350
|
for (let originalIndex2 = original.length - 1; originalIndex2 >= 0; --originalIndex2) {
|
|
4336
4351
|
for (let updatedIndex2 = updated.length - 1; updatedIndex2 >= 0; --updatedIndex2) {
|
|
4337
|
-
lengths[originalIndex2][updatedIndex2] =
|
|
4352
|
+
lengths[originalIndex2][updatedIndex2] = isDeepStrictEqual2(
|
|
4338
4353
|
original[originalIndex2],
|
|
4339
4354
|
updated[updatedIndex2]
|
|
4340
4355
|
) ? (lengths[originalIndex2 + 1][updatedIndex2 + 1] ?? 0) + 1 : Math.max(
|
|
@@ -4347,7 +4362,7 @@ function longestCommonArraySubsequence(original, updated) {
|
|
|
4347
4362
|
let originalIndex = 0;
|
|
4348
4363
|
let updatedIndex = 0;
|
|
4349
4364
|
while (originalIndex < original.length && updatedIndex < updated.length) {
|
|
4350
|
-
if (
|
|
4365
|
+
if (isDeepStrictEqual2(original[originalIndex], updated[updatedIndex])) {
|
|
4351
4366
|
matches.push([originalIndex, updatedIndex]);
|
|
4352
4367
|
originalIndex += 1;
|
|
4353
4368
|
updatedIndex += 1;
|
|
@@ -4403,7 +4418,7 @@ function arrayDiff(original, updated, path32) {
|
|
|
4403
4418
|
return updates;
|
|
4404
4419
|
}
|
|
4405
4420
|
function jsoncUpdatesForObjectDiff(original, updated, path32 = []) {
|
|
4406
|
-
if (
|
|
4421
|
+
if (isDeepStrictEqual2(original, updated)) return [];
|
|
4407
4422
|
if (Array.isArray(original) && Array.isArray(updated)) {
|
|
4408
4423
|
return arrayDiff(original, updated, path32);
|
|
4409
4424
|
}
|
|
@@ -4608,7 +4623,7 @@ function planInstall2(context) {
|
|
|
4608
4623
|
}
|
|
4609
4624
|
settings.hooks = hooks;
|
|
4610
4625
|
migrateDisabledHookIdentifiers(settings, replacedDisabledIdentifiers);
|
|
4611
|
-
if (
|
|
4626
|
+
if (isDeepStrictEqual3(result.data, settings)) {
|
|
4612
4627
|
return unchangedPlan(TARGET_ID3, DISPLAY_NAME3, configPath4);
|
|
4613
4628
|
}
|
|
4614
4629
|
const after = updateJsoncObject(result.source, result.data, settings);
|
|
@@ -4642,7 +4657,7 @@ function planUninstall2(context) {
|
|
|
4642
4657
|
if (!currentHooks) {
|
|
4643
4658
|
const settings2 = structuredClone(result.data);
|
|
4644
4659
|
removeUnusedManagedDisabledIdentifier(settings2);
|
|
4645
|
-
if (
|
|
4660
|
+
if (isDeepStrictEqual3(result.data, settings2)) {
|
|
4646
4661
|
return unchangedPlan(TARGET_ID3, DISPLAY_NAME3, configPath4);
|
|
4647
4662
|
}
|
|
4648
4663
|
const after2 = updateJsoncObject(result.source, result.data, settings2);
|
|
@@ -4675,7 +4690,7 @@ function planUninstall2(context) {
|
|
|
4675
4690
|
if (Object.keys(hooks).length === 0) delete settings.hooks;
|
|
4676
4691
|
else settings.hooks = hooks;
|
|
4677
4692
|
removeUnusedManagedDisabledIdentifier(settings);
|
|
4678
|
-
if (
|
|
4693
|
+
if (isDeepStrictEqual3(result.data, settings)) {
|
|
4679
4694
|
return unchangedPlan(TARGET_ID3, DISPLAY_NAME3, configPath4);
|
|
4680
4695
|
}
|
|
4681
4696
|
const after = updateJsoncObject(result.source, result.data, settings);
|
|
@@ -5038,7 +5053,6 @@ function removeMarketplaceLink(linkPath) {
|
|
|
5038
5053
|
}
|
|
5039
5054
|
|
|
5040
5055
|
// ../../packages/agent-targets/src/mcp/config.ts
|
|
5041
|
-
import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
|
|
5042
5056
|
var FML_MCP_MANAGED_ENV = "FML_MCP_MANAGED";
|
|
5043
5057
|
var FML_MCP_MANAGED_VALUE = "1";
|
|
5044
5058
|
function asRecord4(value) {
|
|
@@ -5094,7 +5108,7 @@ function upsertFmlMcpServerConfig(existing, key, serverConfig) {
|
|
|
5094
5108
|
[FML_MCP_MANAGED_ENV]: FML_MCP_MANAGED_VALUE
|
|
5095
5109
|
}
|
|
5096
5110
|
};
|
|
5097
|
-
if (
|
|
5111
|
+
if (isConfigValueEqual(existingFml, nextFml)) {
|
|
5098
5112
|
return existing;
|
|
5099
5113
|
}
|
|
5100
5114
|
servers.fml = nextFml;
|
|
@@ -5135,18 +5149,17 @@ import path18 from "path";
|
|
|
5135
5149
|
import { parse as parse4 } from "smol-toml";
|
|
5136
5150
|
|
|
5137
5151
|
// ../../packages/agent-targets/src/mcp/toml.ts
|
|
5138
|
-
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
5139
5152
|
function hasOwn3(record, key) {
|
|
5140
5153
|
return Object.prototype.hasOwnProperty.call(record, key);
|
|
5141
5154
|
}
|
|
5142
5155
|
function updateTomlTopLevelTable(source, original, updated, tableKey) {
|
|
5143
|
-
if (
|
|
5156
|
+
if (isConfigValueEqual(original[tableKey], updated[tableKey])) return source;
|
|
5144
5157
|
return updateTomlPaths(source, updated, [{ path: [tableKey] }]);
|
|
5145
5158
|
}
|
|
5146
5159
|
function updateTomlMcpConfig(source, original, updated, configKey) {
|
|
5147
5160
|
const originalServers = configRecord(original[configKey]) ?? {};
|
|
5148
5161
|
const updatedServers = configRecord(updated[configKey]) ?? {};
|
|
5149
|
-
const rewriteFml = !
|
|
5162
|
+
const rewriteFml = !isConfigValueEqual(
|
|
5150
5163
|
originalServers.fml,
|
|
5151
5164
|
updatedServers.fml
|
|
5152
5165
|
);
|
|
@@ -5910,7 +5923,6 @@ import path29 from "path";
|
|
|
5910
5923
|
import path25 from "path";
|
|
5911
5924
|
|
|
5912
5925
|
// ../../packages/agent-targets/src/install/otel/shared.ts
|
|
5913
|
-
import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
|
|
5914
5926
|
function asRecord5(value) {
|
|
5915
5927
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
5916
5928
|
}
|
|
@@ -5961,13 +5973,13 @@ function readJsonc(snapshot) {
|
|
|
5961
5973
|
}
|
|
5962
5974
|
}
|
|
5963
5975
|
function jsoncMutation(snapshot, result, updated) {
|
|
5964
|
-
if (
|
|
5976
|
+
if (isConfigValueEqual(result.data, updated)) return null;
|
|
5965
5977
|
const after = Object.keys(updated).length === 0 ? null : updateJsoncObject(result.source, result.data, updated);
|
|
5966
5978
|
return changedMutation2(snapshot, after);
|
|
5967
5979
|
}
|
|
5968
5980
|
function firstConflict(existing, managed) {
|
|
5969
5981
|
for (const [key, value] of Object.entries(managed)) {
|
|
5970
|
-
if (Object.prototype.hasOwnProperty.call(existing, key) && !
|
|
5982
|
+
if (Object.prototype.hasOwnProperty.call(existing, key) && !isConfigValueEqual(existing[key], value)) {
|
|
5971
5983
|
return key;
|
|
5972
5984
|
}
|
|
5973
5985
|
}
|
|
@@ -5978,7 +5990,7 @@ function containsManagedValues(existing, managed) {
|
|
|
5978
5990
|
if (!Object.prototype.hasOwnProperty.call(existing, key)) return false;
|
|
5979
5991
|
const existingRecord = asRecord5(existing[key]);
|
|
5980
5992
|
const expectedRecord = asRecord5(expected);
|
|
5981
|
-
return existingRecord && expectedRecord ? containsManagedValues(existingRecord, expectedRecord) :
|
|
5993
|
+
return existingRecord && expectedRecord ? containsManagedValues(existingRecord, expectedRecord) : isConfigValueEqual(existing[key], expected);
|
|
5982
5994
|
});
|
|
5983
5995
|
}
|
|
5984
5996
|
function mergeManagedValues(existing, managed) {
|
|
@@ -6005,7 +6017,7 @@ function removeMatchingManagedValues(existing, managed) {
|
|
|
6005
6017
|
if (Object.keys(nested.value).length === 0) delete value[key];
|
|
6006
6018
|
else value[key] = nested.value;
|
|
6007
6019
|
changed = true;
|
|
6008
|
-
} else if (
|
|
6020
|
+
} else if (isConfigValueEqual(value[key], expected)) {
|
|
6009
6021
|
delete value[key];
|
|
6010
6022
|
changed = true;
|
|
6011
6023
|
}
|
|
@@ -6216,7 +6228,6 @@ var CLAUDE_OTEL_INSTALLER = Object.freeze({
|
|
|
6216
6228
|
});
|
|
6217
6229
|
|
|
6218
6230
|
// ../../packages/agent-targets/src/install/otel/codex.ts
|
|
6219
|
-
import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
|
|
6220
6231
|
import path26 from "path";
|
|
6221
6232
|
import { parse as parse5 } from "smol-toml";
|
|
6222
6233
|
var TARGET14 = agentTarget("codex");
|
|
@@ -6349,7 +6360,7 @@ function planInstall6(context) {
|
|
|
6349
6360
|
result.data.otel,
|
|
6350
6361
|
context.configOwnershipRecorded === true
|
|
6351
6362
|
);
|
|
6352
|
-
if (result.data.otel !== void 0 && !
|
|
6363
|
+
if (result.data.otel !== void 0 && !isConfigValueEqual(result.data.otel, managed) && !isPriorManagedConfig) {
|
|
6353
6364
|
return skippedPlan3(
|
|
6354
6365
|
TARGET_ID6,
|
|
6355
6366
|
DISPLAY_NAME6,
|
|
@@ -6358,7 +6369,7 @@ function planInstall6(context) {
|
|
|
6358
6369
|
"existing user-level otel table is not managed by FML"
|
|
6359
6370
|
);
|
|
6360
6371
|
}
|
|
6361
|
-
if (
|
|
6372
|
+
if (isConfigValueEqual(result.data.otel, managed)) {
|
|
6362
6373
|
return unchangedPlan2(TARGET_ID6, DISPLAY_NAME6, settingsPath2, AUTHENTICATION2);
|
|
6363
6374
|
}
|
|
6364
6375
|
const currentOtel = asRecord5(result.data.otel) ?? {};
|
|
@@ -9725,7 +9736,7 @@ async function handleConfigDetail(opts) {
|
|
|
9725
9736
|
// src/commands/tools.ts
|
|
9726
9737
|
import { readFileSync } from "fs";
|
|
9727
9738
|
import path31 from "path";
|
|
9728
|
-
var pluginVersion = true ? "0.8.
|
|
9739
|
+
var pluginVersion = true ? "0.8.12+bc772cee" : void 0;
|
|
9729
9740
|
async function getApi() {
|
|
9730
9741
|
const api = await getAuthenticatedClient();
|
|
9731
9742
|
if (!api) {
|
|
@@ -9882,7 +9893,7 @@ if (process.argv.length <= 2 || process.argv.includes("--help") || process.argv.
|
|
|
9882
9893
|
printBanner();
|
|
9883
9894
|
}
|
|
9884
9895
|
var program = new Command().name("fml").description("FML CLI and agent tools").version(
|
|
9885
|
-
true ? "0.8.
|
|
9896
|
+
true ? "0.8.12+bc772cee" : "dev"
|
|
9886
9897
|
);
|
|
9887
9898
|
function formatCommandInventory(cmd, prefix = "") {
|
|
9888
9899
|
const name = prefix ? `${prefix} ${cmd.name()}` : cmd.name();
|
package/dist/mcp/server.js
CHANGED
|
@@ -302,6 +302,102 @@ function registerTools(server2, environment = getActiveEnv()) {
|
|
|
302
302
|
async (args) => handleTool(tool.mastraId, args)
|
|
303
303
|
);
|
|
304
304
|
}
|
|
305
|
+
const gcpBillingDateArgs = {
|
|
306
|
+
sourceId: z.string().min(1).describe(
|
|
307
|
+
"Organization-owned trusted source ID from gcp_billing_sources."
|
|
308
|
+
),
|
|
309
|
+
startDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Inclusive usage start date in YYYY-MM-DD format."),
|
|
310
|
+
endDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe(
|
|
311
|
+
"Exclusive usage end date in YYYY-MM-DD format; date ranges may span at most 366 days."
|
|
312
|
+
)
|
|
313
|
+
};
|
|
314
|
+
const gcpBillingFilters = z.object({
|
|
315
|
+
projectIds: z.array(z.string().min(1).max(200)).max(50).optional().describe(
|
|
316
|
+
"Optional GCP project IDs. Omit to include account-level charges; an empty array matches no rows."
|
|
317
|
+
),
|
|
318
|
+
serviceIds: z.array(z.string().max(200)).max(50).optional().describe("GCP service IDs."),
|
|
319
|
+
skuIds: z.array(z.string().max(200)).max(50).optional().describe("GCP SKU IDs."),
|
|
320
|
+
locations: z.array(z.string().max(200)).max(50).optional().describe("Usage locations."),
|
|
321
|
+
resourceNames: z.array(z.string().min(1).max(2048)).max(50).optional().describe(
|
|
322
|
+
"Canonical resource global names; an empty array matches no rows."
|
|
323
|
+
),
|
|
324
|
+
labels: z.array(
|
|
325
|
+
z.object({
|
|
326
|
+
scope: z.enum(["resource", "project"]),
|
|
327
|
+
key: z.string().min(1).max(63),
|
|
328
|
+
values: z.array(z.string().max(63)).max(50)
|
|
329
|
+
}).strict()
|
|
330
|
+
).max(10).optional().describe(
|
|
331
|
+
"Label selectors are ANDed; values within each selector are ORed. Empty values match no rows; an empty selector list is unrestricted. Empty label values are valid."
|
|
332
|
+
)
|
|
333
|
+
}).strict().optional().describe(
|
|
334
|
+
"Optional account billing filters; omitted means unrestricted within the account. Empty project/service/SKU/location/resource arrays or label value arrays match no rows; an empty labels list is unrestricted."
|
|
335
|
+
);
|
|
336
|
+
server2.tool(
|
|
337
|
+
"gcp_billing_sources",
|
|
338
|
+
"List the organization's saved GCP billing connection and account sources. A saved credential does not prove source access.",
|
|
339
|
+
{},
|
|
340
|
+
async () => handleTool("gcp-billing-sources", {})
|
|
341
|
+
);
|
|
342
|
+
server2.tool(
|
|
343
|
+
"gcp_billing_describe",
|
|
344
|
+
"Describe a detailed account billing export table or view, date coverage and export freshness. Account check is matched only when the bounded query returns rows; zero rows remain unverified.",
|
|
345
|
+
gcpBillingDateArgs,
|
|
346
|
+
async (args) => handleTool("gcp-billing-describe", args)
|
|
347
|
+
);
|
|
348
|
+
server2.tool(
|
|
349
|
+
"gcp_billing_summary",
|
|
350
|
+
"Summarize bounded billing account costs with optional project, service, SKU, location, resource and scoped label filters. Group by resource global name or a selected resource/project label. Account-level rows are included unless projects are filtered; credits count once and currencies stay separate. includeUsage defaults to false; true automatically adds SKU and usage/pricing unit groups, returning quantities as precision-preserving decimal strings without combining SKUs or units.",
|
|
351
|
+
{
|
|
352
|
+
...gcpBillingDateArgs,
|
|
353
|
+
dimensions: z.array(
|
|
354
|
+
z.enum([
|
|
355
|
+
"usageDate",
|
|
356
|
+
"service",
|
|
357
|
+
"sku",
|
|
358
|
+
"location",
|
|
359
|
+
"project",
|
|
360
|
+
"invoiceMonth",
|
|
361
|
+
"costType",
|
|
362
|
+
"resource",
|
|
363
|
+
"label",
|
|
364
|
+
"usageUnit",
|
|
365
|
+
"pricingUnit"
|
|
366
|
+
])
|
|
367
|
+
).max(11).optional().describe(
|
|
368
|
+
"Optional grouping dimensions: usageDate, service, sku, location, project, invoiceMonth, costType, resource, label, usageUnit, pricingUnit. Resource uses canonical global names; selected-label grouping keeps unlabeled rows as null. Currency is always grouped separately."
|
|
369
|
+
),
|
|
370
|
+
label: z.object({
|
|
371
|
+
scope: z.enum(["resource", "project"]),
|
|
372
|
+
key: z.string().min(1).max(63)
|
|
373
|
+
}).strict().optional().describe("Required exactly when dimensions includes label."),
|
|
374
|
+
includeUsage: z.boolean().optional().describe(
|
|
375
|
+
"Defaults to false (cost only). True returns usageAmount and usageAmountInPricingUnits as precision-preserving decimal strings and automatically adds sku, usageUnit and pricingUnit grouping without combining SKUs or units. Returned dimensions include these groups."
|
|
376
|
+
),
|
|
377
|
+
filters: gcpBillingFilters
|
|
378
|
+
},
|
|
379
|
+
async (args) => {
|
|
380
|
+
if ((args.dimensions?.includes("label") ?? false) !== (args.label !== void 0)) {
|
|
381
|
+
return errorResult(
|
|
382
|
+
"label is required exactly when dimensions includes label"
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
return handleTool("gcp-billing-summary", args);
|
|
386
|
+
}
|
|
387
|
+
);
|
|
388
|
+
server2.tool(
|
|
389
|
+
"gcp_billing_records",
|
|
390
|
+
"Read a bounded page of detailed billing account records, including nullable projects and nested credits, labels, tags, resources and adjustments. Supports project, service, SKU, location, canonical resource and scoped label filters. Keep source, dates, filters and page size unchanged when using the cursor.",
|
|
391
|
+
{
|
|
392
|
+
...gcpBillingDateArgs,
|
|
393
|
+
filters: gcpBillingFilters,
|
|
394
|
+
pageSize: z.number().int().min(1).max(200).optional().describe("Records per page: integer from 1 to 200; defaults to 50."),
|
|
395
|
+
cursor: z.string().max(256).optional().describe(
|
|
396
|
+
"Opaque cursor from the preceding page; reuse with the same source, dates, and filters."
|
|
397
|
+
)
|
|
398
|
+
},
|
|
399
|
+
async (args) => handleTool("gcp-billing-records", args)
|
|
400
|
+
);
|
|
305
401
|
server2.tool(
|
|
306
402
|
"get_engineering_activity",
|
|
307
403
|
"Get agent activity summary (Claude Code, Codex, Gemini CLI, Mastra). SCOPES: 'org' (default), 'project', or 'user' (by githubUsername).",
|
package/dist/observer-server.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
isWinShim,
|
|
6
6
|
quoteWinArg,
|
|
7
7
|
resolveBin
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-Z7MXNJ6X.js";
|
|
9
9
|
import {
|
|
10
10
|
createHookSyncLoop,
|
|
11
11
|
getActiveHookDestinationBinding
|
|
@@ -1563,7 +1563,7 @@ var hookRejectionStatus = () => ({
|
|
|
1563
1563
|
...lastRejectedReason !== void 0 ? { lastRejectedReason } : {},
|
|
1564
1564
|
...lastRejectedTarget !== void 0 ? { lastRejectedTarget } : {}
|
|
1565
1565
|
});
|
|
1566
|
-
var packageVersion = true ? "0.8.
|
|
1566
|
+
var packageVersion = true ? "0.8.12+bc772cee" : "dev";
|
|
1567
1567
|
var health = () => ({
|
|
1568
1568
|
status: "ok",
|
|
1569
1569
|
service: OBSERVER_SERVICE_NAME,
|