@clawdbuilder/jig-bedrock 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -154,7 +154,16 @@ mode bits), and the no-browser fallback is the WSL-only `bin/windows-browser` sh
154
154
  | `/bedrock-doctor` | Probe Node, AWS CLI, bash, jq and the optional usage program; it does not call AWS |
155
155
 
156
156
  The footer and `/bedrock-usage` read an executable named `usage` in `usageDir`; it is called with `--daily`,
157
- `--weekly` or `--monthly` and `--output json`, and prints the spend as JSON.
157
+ `--weekly` or `--monthly` and `--output json`, and prints the spend as JSON. It receives `AWS_PROFILE` and
158
+ `BEDROCK_REGIONS` in its environment.
159
+
160
+ If your usage CLI's own command is `usage-cli`, put this two-line wrapper at
161
+ `~/.local/share/usage-tool/usage` and make it executable:
162
+
163
+ ```sh
164
+ #!/bin/sh
165
+ exec usage-cli usage "$@"
166
+ ```
158
167
 
159
168
  ## Tests
160
169
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbuilder/jig-bedrock",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Claude on AWS Bedrock for Pi: inference-profile discovery, the Messages route with cache-friendly tools, Converse fallback, SSO repair and a budget footer.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/sso-check.ts CHANGED
@@ -100,12 +100,18 @@ export async function checkSso(
100
100
  ): Promise<SsoState> {
101
101
  // The fast path: a cached token that stays valid needs no network check and no SDK.
102
102
  if (cachedTokenFresh(profile, deps)) return "ok";
103
- const limit = AbortSignal.timeout(deps.timeoutMs);
103
+ // `AbortSignal.timeout` uses an unreferenced timer. With a stalled SDK and nothing else in the event loop, the process
104
+ // would exit before the check could return an error. A referenced timer keeps the check alive for its own timeout.
105
+ const controller = new AbortController();
106
+ const limit = controller.signal;
107
+ const timer = setTimeout(() => controller.abort(), deps.timeoutMs);
104
108
  try {
105
109
  // The SDK's answer is dropped: only whether it resolved matters.
106
110
  await until(deps.credentialProvider()({ profile })(), signal ? AbortSignal.any([signal, limit]) : limit);
107
111
  return "ok";
108
112
  } catch (error) {
109
113
  return classify(error);
114
+ } finally {
115
+ clearTimeout(timer);
110
116
  }
111
117
  }
package/src/statistics.ts CHANGED
@@ -250,24 +250,20 @@ export function createStatistics(
250
250
  previous = load(period);
251
251
  if (!options.force && previous && !previous.stale) return previous;
252
252
  try {
253
- const output = await runner(
254
- usageExecutable(config),
255
- ["usage", `--${period}`, "--output", "json", "--aws-profile", config.profile],
256
- {
257
- timeout: 120_000,
258
- maxBuffer: 2_097_152,
259
- signal: options.signal,
260
- env: {
261
- ...process.env,
262
- BEDROCK_REGIONS: config.regions.join(","),
263
- AWS_PROFILE: config.profile,
264
- AWS_CLI_AUTO_PROMPT: "off",
265
- AWS_PAGER: "",
266
- NO_COLOR: "1",
267
- PAT_SKIP_UPDATE_CHECK: "1",
268
- },
253
+ const output = await runner(usageExecutable(config), [`--${period}`, "--output", "json"], {
254
+ timeout: 120_000,
255
+ maxBuffer: 2_097_152,
256
+ signal: options.signal,
257
+ env: {
258
+ ...process.env,
259
+ BEDROCK_REGIONS: config.regions.join(","),
260
+ AWS_PROFILE: config.profile,
261
+ AWS_CLI_AUTO_PROMPT: "off",
262
+ AWS_PAGER: "",
263
+ NO_COLOR: "1",
264
+ PAT_SKIP_UPDATE_CHECK: "1",
269
265
  },
270
- );
266
+ });
271
267
  if (options.signal?.aborted) throw new UsageError("cancelled");
272
268
  const observedAt = now();
273
269
  // Legacy reports have no explicit range, so a UTC rollover cannot be safely relabelled.
package/src/usage.ts CHANGED
@@ -113,8 +113,9 @@ export const runUsage: UsageRunner = (program, args, options) =>
113
113
  );
114
114
  child.on("close", (code) => finish(code === 0 ? undefined : new UsageError(classify(stderr))));
115
115
  options.signal?.addEventListener("abort", abort, { once: true });
116
+ // A referenced timer keeps a stalled program's timeout alive when nothing else holds the event loop. It is
117
+ // cleared in finish(), so a program that answers does not delay exit.
116
118
  timer = setTimeout(() => finish(new UsageError("timeout")), options.timeout);
117
- timer.unref();
118
119
  if (options.signal?.aborted) abort();
119
120
  });
120
121
  export const usageExecutable = (config: ResolvedConfig): string =>