@danypops/vehicle-core 0.17.1 → 0.18.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.
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The Grant primitive's own wire-neutral shape: a resource budget bounding how much an
3
+ * already-authorized, already-running long-running operation may still do before it must ask
4
+ * for more. Mirrors VehicleJobWakeBudget's own convention (a plain, optional-per-dimension
5
+ * object, not a class) -- see wake-log.ts's own doc comment for that precedent. Every dimension
6
+ * is independently optional: a caller states only the ceilings that matter for its own operation
7
+ * (an operation with no real notion of "tokens" simply never sets maxTokens).
8
+ *
9
+ * Deliberately agent-flavored (turns/tool-calls/tokens) rather than a generic {maxCount, maxBytes}
10
+ * pair the way VehicleJobWakeBudget is -- Vehicle was built specifically for agent consumers
11
+ * (vehicle-client-pi exists precisely to project operations as Pi tools), so this vocabulary
12
+ * belongs here rather than being reinvented per-consumer.
13
+ */
14
+ export interface VehicleGrantBudget {
15
+ readonly maxTurns?: number;
16
+ readonly maxToolCalls?: number;
17
+ readonly maxTokens?: number;
18
+ readonly maxWallClockMs?: number;
19
+ }
20
+ /**
21
+ * True the moment any one *set* dimension reaches zero or below -- the tightest dimension
22
+ * governs, not an average or a sum. A dimension the caller never set imposes no ceiling of its
23
+ * own. An entirely empty budget ({}) is never exhausted: that's an unbounded grant (every
24
+ * dimension omitted), not a zero one -- a caller that wants "no more of anything" states at
25
+ * least one dimension as 0, it doesn't rely on {} meaning that.
26
+ */
27
+ export declare function grantBudgetExhausted(remaining: VehicleGrantBudget): boolean;
28
+ /**
29
+ * Adds a top-up onto the current remaining budget, dimension by dimension. A dimension absent
30
+ * from the top-up is left exactly as it was; a dimension the current budget never had but the
31
+ * top-up introduces is taken as-is (not added to an implicit 0, since the current budget's own
32
+ * "never set" already means unbounded for that dimension -- introducing a ceiling for the first
33
+ * time via a top-up is a real, deliberate narrowing a caller must do explicitly, not an artifact
34
+ * of the merge itself).
35
+ */
36
+ export declare function mergeGrantBudget(current: VehicleGrantBudget, additional: VehicleGrantBudget): VehicleGrantBudget;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * True the moment any one *set* dimension reaches zero or below -- the tightest dimension
3
+ * governs, not an average or a sum. A dimension the caller never set imposes no ceiling of its
4
+ * own. An entirely empty budget ({}) is never exhausted: that's an unbounded grant (every
5
+ * dimension omitted), not a zero one -- a caller that wants "no more of anything" states at
6
+ * least one dimension as 0, it doesn't rely on {} meaning that.
7
+ */
8
+ export function grantBudgetExhausted(remaining) {
9
+ return ((remaining.maxTurns !== undefined && remaining.maxTurns <= 0) ||
10
+ (remaining.maxToolCalls !== undefined && remaining.maxToolCalls <= 0) ||
11
+ (remaining.maxTokens !== undefined && remaining.maxTokens <= 0) ||
12
+ (remaining.maxWallClockMs !== undefined && remaining.maxWallClockMs <= 0));
13
+ }
14
+ /**
15
+ * Adds a top-up onto the current remaining budget, dimension by dimension. A dimension absent
16
+ * from the top-up is left exactly as it was; a dimension the current budget never had but the
17
+ * top-up introduces is taken as-is (not added to an implicit 0, since the current budget's own
18
+ * "never set" already means unbounded for that dimension -- introducing a ceiling for the first
19
+ * time via a top-up is a real, deliberate narrowing a caller must do explicitly, not an artifact
20
+ * of the merge itself).
21
+ */
22
+ export function mergeGrantBudget(current, additional) {
23
+ const merged = { ...current };
24
+ for (const key of ["maxTurns", "maxToolCalls", "maxTokens", "maxWallClockMs"]) {
25
+ const addition = additional[key];
26
+ if (addition === undefined)
27
+ continue;
28
+ merged[key] = (current[key] ?? 0) + addition;
29
+ }
30
+ return merged;
31
+ }
@@ -1,3 +1,4 @@
1
+ export * from "./grant.js";
1
2
  export * from "./identity.js";
2
3
  export * from "./replay.js";
3
4
  export * from "./retention.js";
@@ -1,3 +1,4 @@
1
+ export * from "./grant.js";
1
2
  export * from "./identity.js";
2
3
  export * from "./replay.js";
3
4
  export * from "./retention.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/vehicle-core",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "description": "Vehicle's runtime-neutral wire contract: operation descriptors, schema codecs, failure shapes. Zero runtime dependencies, zero Bun-specific code -- the one thing every Vehicle client and server package depends on.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The Grant primitive's own wire-neutral shape: a resource budget bounding how much an
3
+ * already-authorized, already-running long-running operation may still do before it must ask
4
+ * for more. Mirrors VehicleJobWakeBudget's own convention (a plain, optional-per-dimension
5
+ * object, not a class) -- see wake-log.ts's own doc comment for that precedent. Every dimension
6
+ * is independently optional: a caller states only the ceilings that matter for its own operation
7
+ * (an operation with no real notion of "tokens" simply never sets maxTokens).
8
+ *
9
+ * Deliberately agent-flavored (turns/tool-calls/tokens) rather than a generic {maxCount, maxBytes}
10
+ * pair the way VehicleJobWakeBudget is -- Vehicle was built specifically for agent consumers
11
+ * (vehicle-client-pi exists precisely to project operations as Pi tools), so this vocabulary
12
+ * belongs here rather than being reinvented per-consumer.
13
+ */
14
+ export interface VehicleGrantBudget {
15
+ readonly maxTurns?: number;
16
+ readonly maxToolCalls?: number;
17
+ readonly maxTokens?: number;
18
+ readonly maxWallClockMs?: number;
19
+ }
20
+
21
+ /**
22
+ * True the moment any one *set* dimension reaches zero or below -- the tightest dimension
23
+ * governs, not an average or a sum. A dimension the caller never set imposes no ceiling of its
24
+ * own. An entirely empty budget ({}) is never exhausted: that's an unbounded grant (every
25
+ * dimension omitted), not a zero one -- a caller that wants "no more of anything" states at
26
+ * least one dimension as 0, it doesn't rely on {} meaning that.
27
+ */
28
+ export function grantBudgetExhausted(remaining: VehicleGrantBudget): boolean {
29
+ return (
30
+ (remaining.maxTurns !== undefined && remaining.maxTurns <= 0) ||
31
+ (remaining.maxToolCalls !== undefined && remaining.maxToolCalls <= 0) ||
32
+ (remaining.maxTokens !== undefined && remaining.maxTokens <= 0) ||
33
+ (remaining.maxWallClockMs !== undefined && remaining.maxWallClockMs <= 0)
34
+ );
35
+ }
36
+
37
+ /**
38
+ * Adds a top-up onto the current remaining budget, dimension by dimension. A dimension absent
39
+ * from the top-up is left exactly as it was; a dimension the current budget never had but the
40
+ * top-up introduces is taken as-is (not added to an implicit 0, since the current budget's own
41
+ * "never set" already means unbounded for that dimension -- introducing a ceiling for the first
42
+ * time via a top-up is a real, deliberate narrowing a caller must do explicitly, not an artifact
43
+ * of the merge itself).
44
+ */
45
+ export function mergeGrantBudget(current: VehicleGrantBudget, additional: VehicleGrantBudget): VehicleGrantBudget {
46
+ const merged: { -readonly [K in keyof VehicleGrantBudget]?: number } = { ...current };
47
+ for (const key of ["maxTurns", "maxToolCalls", "maxTokens", "maxWallClockMs"] as const) {
48
+ const addition = additional[key];
49
+ if (addition === undefined) continue;
50
+ merged[key] = (current[key] ?? 0) + addition;
51
+ }
52
+ return merged;
53
+ }
package/src/jobs/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./grant.js";
1
2
  export * from "./identity.js";
2
3
  export * from "./replay.js";
3
4
  export * from "./retention.js";