@stigg/agent-sdk-js 0.0.0-stage → 0.1.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.
Files changed (98) hide show
  1. package/README.md +1296 -2
  2. package/dist/bindings/client/core/registry.d.ts +12 -0
  3. package/dist/bindings/client/core/registry.js +22 -0
  4. package/dist/bindings/client/core/types.d.ts +117 -0
  5. package/dist/bindings/client/core/types.js +13 -0
  6. package/dist/bindings/client/core/wrap-client.d.ts +6 -0
  7. package/dist/bindings/client/core/wrap-client.js +258 -0
  8. package/dist/bindings/client/gateways/bedrock/bedrock-recipe.d.ts +17 -0
  9. package/dist/bindings/client/gateways/bedrock/bedrock-recipe.js +134 -0
  10. package/dist/bindings/client/gateways/bedrock/types.d.ts +13 -0
  11. package/dist/bindings/client/gateways/bedrock/types.js +2 -0
  12. package/dist/bindings/client/gateways/litellm/litellm-recipe.d.ts +17 -0
  13. package/dist/bindings/client/gateways/litellm/litellm-recipe.js +171 -0
  14. package/dist/bindings/client/gateways/litellm/types.d.ts +30 -0
  15. package/dist/bindings/client/gateways/litellm/types.js +2 -0
  16. package/dist/bindings/client/gateways/openrouter/openrouter-recipe.d.ts +20 -0
  17. package/dist/bindings/client/gateways/openrouter/openrouter-recipe.js +244 -0
  18. package/dist/bindings/client/gateways/openrouter/sdk-usage.d.ts +37 -0
  19. package/dist/bindings/client/gateways/openrouter/sdk-usage.js +63 -0
  20. package/dist/bindings/client/gateways/openrouter/types.d.ts +78 -0
  21. package/dist/bindings/client/gateways/openrouter/types.js +2 -0
  22. package/dist/bindings/client/providers/anthropic/anthropic-recipe.d.ts +34 -0
  23. package/dist/bindings/client/providers/anthropic/anthropic-recipe.js +169 -0
  24. package/dist/bindings/client/providers/gemini/gemini-recipe.d.ts +54 -0
  25. package/dist/bindings/client/providers/gemini/gemini-recipe.js +243 -0
  26. package/dist/bindings/client/providers/groq/groq-recipe.d.ts +20 -0
  27. package/dist/bindings/client/providers/groq/groq-recipe.js +101 -0
  28. package/dist/bindings/client/providers/mistral/mistral-recipe.d.ts +22 -0
  29. package/dist/bindings/client/providers/mistral/mistral-recipe.js +114 -0
  30. package/dist/bindings/client/providers/mistral/types.d.ts +38 -0
  31. package/dist/bindings/client/providers/mistral/types.js +2 -0
  32. package/dist/bindings/client/providers/ollama/ollama-recipe.d.ts +31 -0
  33. package/dist/bindings/client/providers/ollama/ollama-recipe.js +107 -0
  34. package/dist/bindings/client/providers/ollama/types.d.ts +24 -0
  35. package/dist/bindings/client/providers/ollama/types.js +2 -0
  36. package/dist/bindings/client/providers/openai/openai-recipe.d.ts +71 -0
  37. package/dist/bindings/client/providers/openai/openai-recipe.js +122 -0
  38. package/dist/bindings/client/providers/typesafe/typesafe-recipe.d.ts +44 -0
  39. package/dist/bindings/client/providers/typesafe/typesafe-recipe.js +83 -0
  40. package/dist/bindings/proxy/headers.d.ts +6 -0
  41. package/dist/bindings/proxy/headers.js +12 -0
  42. package/dist/bindings/proxy/index.d.ts +21 -0
  43. package/dist/bindings/proxy/index.js +18 -0
  44. package/dist/bindings/proxy/types.d.ts +8 -0
  45. package/dist/bindings/proxy/types.js +2 -0
  46. package/dist/bindings/shared/estimate.d.ts +27 -0
  47. package/dist/bindings/shared/estimate.js +38 -0
  48. package/dist/bindings/shared/meter-stream.d.ts +18 -0
  49. package/dist/bindings/shared/meter-stream.js +151 -0
  50. package/dist/bindings/shared/token-usage.d.ts +240 -0
  51. package/dist/bindings/shared/token-usage.js +574 -0
  52. package/dist/bindings/shared/types.d.ts +129 -0
  53. package/dist/bindings/shared/types.js +2 -0
  54. package/dist/bindings/shared/weighted-metrics.d.ts +37 -0
  55. package/dist/bindings/shared/weighted-metrics.js +47 -0
  56. package/dist/config.d.ts +145 -0
  57. package/dist/config.js +99 -0
  58. package/dist/core/context.d.ts +160 -0
  59. package/dist/core/context.js +221 -0
  60. package/dist/core/dimensions.d.ts +22 -0
  61. package/dist/core/dimensions.js +47 -0
  62. package/dist/core/hooks.d.ts +21 -0
  63. package/dist/core/hooks.js +47 -0
  64. package/dist/core/session.d.ts +190 -0
  65. package/dist/core/session.js +448 -0
  66. package/dist/decision-text.d.ts +15 -0
  67. package/dist/decision-text.js +54 -0
  68. package/dist/engine/composite-engine.d.ts +72 -0
  69. package/dist/engine/composite-engine.js +135 -0
  70. package/dist/engine/create-engine.d.ts +16 -0
  71. package/dist/engine/create-engine.js +93 -0
  72. package/dist/engine/decision.d.ts +42 -0
  73. package/dist/engine/decision.js +135 -0
  74. package/dist/engine/engine.d.ts +166 -0
  75. package/dist/engine/engine.js +11 -0
  76. package/dist/engine/node-sdk-engine.d.ts +125 -0
  77. package/dist/engine/node-sdk-engine.js +262 -0
  78. package/dist/engine/report.d.ts +106 -0
  79. package/dist/engine/report.js +188 -0
  80. package/dist/engine/rest-governance-engine.d.ts +47 -0
  81. package/dist/engine/rest-governance-engine.js +220 -0
  82. package/dist/errors.d.ts +86 -0
  83. package/dist/errors.js +161 -0
  84. package/dist/headers.d.ts +40 -0
  85. package/dist/headers.js +82 -0
  86. package/dist/index.d.ts +57 -0
  87. package/dist/index.js +106 -0
  88. package/dist/internal.d.ts +33 -0
  89. package/dist/internal.js +87 -0
  90. package/dist/logger.d.ts +15 -0
  91. package/dist/logger.js +20 -0
  92. package/dist/sdk-identity.d.ts +36 -0
  93. package/dist/sdk-identity.js +43 -0
  94. package/dist/stigg-agent-sdk.d.ts +300 -0
  95. package/dist/stigg-agent-sdk.js +656 -0
  96. package/dist/types.d.ts +642 -0
  97. package/dist/types.js +147 -0
  98. package/package.json +89 -3
package/dist/types.js ADDED
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unitsPerTokens = exports.wholeUnitsForGovernance = exports.toMeasurement = exports.vendorMetrics = exports.emptyTokenUsage = exports.entitlementRef = exports.entitlementKind = exports.entitlementId = void 0;
4
+ exports.entitlementError = entitlementError;
5
+ exports.usageValueError = usageValueError;
6
+ /**
7
+ * The vocabulary shared by the core, the engines and every binding, and the argument list of
8
+ * every call on the public surface.
9
+ *
10
+ * Terms follow Stigg governance rather than the draft design notes: provision/archive (not
11
+ * register/de-register), ingest (not report), assignment (not budget), dimensions (not tags).
12
+ *
13
+ * The imports below are all `import type`, so they are erased at compile time: this file pulls in
14
+ * no module at runtime and stays the leaf everything else can depend on.
15
+ */
16
+ const errors_1 = require("./errors");
17
+ /** The id to send as `featureId`/`currencyId`, whichever kind the entitlement is. */
18
+ const entitlementId = (entitlement) => entitlement.currencyId ?? entitlement.featureId;
19
+ exports.entitlementId = entitlementId;
20
+ /** 'credit' targets read the customer's credit pool; 'feature' targets need an entitling subscription. */
21
+ const entitlementKind = (entitlement) => entitlement.currencyId ? 'credit' : 'feature';
22
+ exports.entitlementKind = entitlementKind;
23
+ /**
24
+ * The entitlement as every Stigg endpoint takes it: one of two mutually exclusive id fields,
25
+ * ready to spread.
26
+ *
27
+ * ```ts
28
+ * await client.v1Beta.customers.entitlements.check(customerId, { ...entitlementRef(entitlement), requestedUsage });
29
+ * ```
30
+ *
31
+ * Narrowing on the property rather than through {@link entitlementKind} is the point: a function
32
+ * call cannot narrow a union, so every hand-written version of this needed a `!` on each branch -
33
+ * an assertion that the union already guarantees and that would survive the union changing.
34
+ */
35
+ const entitlementRef = (entitlement) => entitlement.currencyId !== undefined ? { currencyId: entitlement.currencyId } : { featureId: entitlement.featureId };
36
+ exports.entitlementRef = entitlementRef;
37
+ /**
38
+ * Why an entitlement cannot be billed against, if one was named at all.
39
+ *
40
+ * Naming none is legal: it is how a caller asks for metering without enforcement, so undefined is
41
+ * not an error here. The one place an entitlement is genuinely required is an assignment, which is
42
+ * written over `(entity x entitlement)` - and `register` refuses that case itself, because only it
43
+ * knows the agent to name in the message.
44
+ *
45
+ * What stays refused is an entitlement that is named and names nothing. The union permits
46
+ * `{ currencyId: '' }`, and an empty currency is falsy - so it classifies as a feature and every
47
+ * branch downstream then asks for a `featureId` that is not there. An empty id is a typo rather
48
+ * than an intention, and letting it through meters a run against nothing while it still looks
49
+ * enforced.
50
+ */
51
+ function entitlementError(entitlement) {
52
+ if (!entitlement)
53
+ return undefined;
54
+ if ((0, exports.entitlementId)(entitlement)?.trim())
55
+ return undefined;
56
+ return new Error('a run needs a non-empty currencyId or featureId - an empty one bills against nothing.');
57
+ }
58
+ const emptyTokenUsage = () => ({ input: 0, output: 0, cacheRead: 0, cacheCreate: 0 });
59
+ exports.emptyTokenUsage = emptyTokenUsage;
60
+ /** What a run reports when nobody says otherwise: exactly what the vendor stated. */
61
+ const vendorMetrics = (measurement) => measurement.metrics ?? {};
62
+ exports.vendorMetrics = vendorMetrics;
63
+ /** A binding may report either shape; `TokenUsage` is the common case and stays terse. */
64
+ const toMeasurement = (value) => 'input' in value ? { usage: value } : value;
65
+ exports.toMeasurement = toMeasurement;
66
+ /**
67
+ * The amount to report when this run is attributed to a governance entity.
68
+ *
69
+ * Governance counts in whole units and cannot be made to count otherwise from here: its ingest
70
+ * schema is `z.number().int()`, and the counter behind it is a Redis `HINCRBY`, which takes an
71
+ * integer delta. A fractional amount is rejected at that boundary - the wallet still moves, the
72
+ * per-entity counter does not, and nothing in the response says so. An agent's budget silently
73
+ * stops advancing while its spend carries on.
74
+ *
75
+ * So an attributed run rounds up, and only an attributed run: a run that names no entity reports
76
+ * what its mapper produced, because the wallet takes fractions and nothing downstream of it
77
+ * counts in whole units.
78
+ *
79
+ * Rounding *up* rather than to nearest, because a call that happened must cost something: at any
80
+ * sane denomination most calls are worth less than one unit, and rounding to nearest would bill
81
+ * nothing for nearly all of them.
82
+ *
83
+ * TODO: delete this, and the call sites that use it, once governance counts fractional usage.
84
+ * The platform fix is to scale internally - store micro-units and accept fractions at the API
85
+ * boundary - which keeps `HINCRBY` working and is the only way an agent budget can be
86
+ * denominated finely enough to price a call worth a tenth of a cent. Until then this is a
87
+ * deliberate overcharge on small calls, which is why it is announced rather than silent.
88
+ */
89
+ const wholeUnitsForGovernance = (value) => Math.ceil(value);
90
+ exports.wholeUnitsForGovernance = wholeUnitsForGovernance;
91
+ /**
92
+ * Why a measured value cannot be reported, if it cannot.
93
+ *
94
+ * Zero is not an error - a cached refusal or an empty stream is a normal turn - but a mapper
95
+ * dividing by an unset config returns NaN or Infinity, and reading those as "nothing was used"
96
+ * meters the run at zero while every call still reports success. Those are refused everywhere.
97
+ *
98
+ * A fraction is refused on one path only, and the rule is the endpoint's rather than this SDK's:
99
+ *
100
+ * - **The wallet** takes them. `credits.consumption.consume` and its async twin accept a
101
+ * fractional `amount`, and balances are fractional too - which they have to be, or a currency
102
+ * could never be denominated finely enough to price a call worth a tenth of a cent.
103
+ * - **An event** takes them. The number rides as a dimension and a meter sums what it finds,
104
+ * which is the only way a gateway's `cost` reports honestly.
105
+ * - **The usage report** does not: `POST /api/v1/usage` answers
106
+ * `400 Expected integer, received float`. That is the one case refused here, where the caller
107
+ * can still see which metric it was - metering failures are swallowed into `onError`, so a 400
108
+ * three frames down is a silent gap rather than an error anyone reads.
109
+ *
110
+ * Shared, because every path that reports usage has to answer this the same way.
111
+ */
112
+ function usageValueError(value, mode = 'sync',
113
+ // Whether this metric draws the credit wallet rather than reporting a feature. The wallet takes
114
+ // fractions in both modes, so what the ingest mode decides does not apply to it.
115
+ drawsWallet = false) {
116
+ if (!Number.isFinite(value) || value < 0) {
117
+ return new errors_1.EngineError('ingest', `usage value must be a finite non-negative number, got ${value}`);
118
+ }
119
+ if (mode === 'async' || drawsWallet || Number.isInteger(value))
120
+ return undefined;
121
+ return new errors_1.EngineError('ingest', `usage value must be a whole number to report against a feature, got ${value}. The usage ` +
122
+ 'report takes integers; a credit currency takes fractions, and so does an event under ' +
123
+ "`ingest: 'async'`.");
124
+ }
125
+ /**
126
+ * One metric, summed from every token class and divided by the unit size.
127
+ *
128
+ * The mapper for an application that prices tokens itself. Named for what it produces - units
129
+ * under an id - rather than for credits, because it does not deduct any: it reports a number, and
130
+ * that number draws the wallet only when the id happens to name a credit currency. Which it is
131
+ * decides the whole ingest path, so a mapper that claimed to know was the wrong place to look.
132
+ *
133
+ * **Prefer reporting the raw counters and converting in Stigg.** A consumption mapping on the plan
134
+ * does the same arithmetic where a pricing change does not need a deploy, and it is the only place
135
+ * that can weight cache reads cheaper. Reach for this when the application deliberately prices
136
+ * itself.
137
+ *
138
+ * The division is reported as it comes out. A credit currency takes fractions, so a call worth
139
+ * four fifths of a unit costs four fifths of one - rounding it up here would be this SDK's
140
+ * arithmetic on someone else's price. A **feature** is the exception: `POST /api/v1/usage` takes
141
+ * integers, so pick a `tokensPerUnit` that divides, or round in your own mapper.
142
+ *
143
+ * @param id The Stigg feature id or credit currency id to report under.
144
+ * @param tokensPerUnit How many tokens make one unit.
145
+ */
146
+ const unitsPerTokens = (id, tokensPerUnit = 1) => ({ usage }) => usage ? { [id]: (usage.input + usage.output + usage.cacheRead + usage.cacheCreate) / tokensPerUnit } : {};
147
+ exports.unitsPerTokens = unitsPerTokens;
package/package.json CHANGED
@@ -1,6 +1,92 @@
1
1
  {
2
2
  "name": "@stigg/agent-sdk-js",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Stigg agent SDK (JS) - run-lifecycle governance for agentic stacks, with examples per layer",
5
+ "main": "dist/index.js",
6
+ "typings": "dist/index.d.ts",
7
+ "publishConfig": {
8
+ "access": "public",
9
+ "main": "dist/index.js",
10
+ "typings": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./internal": {
17
+ "types": "./dist/internal.d.ts",
18
+ "default": "./dist/internal.js"
19
+ },
20
+ "./package.json": "./package.json"
21
+ }
22
+ },
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/stiggio/stigg-sdk.git",
27
+ "directory": "packages/agent-sdk/agent-sdk-js"
28
+ },
29
+ "scripts": {
30
+ "build": "rm -rf dist && yarn run -T tsc -p tsconfig.json --noEmit && yarn run -T tsc -p tsconfig.build.json",
31
+ "lint": "yarn run -T eslint \"{src,examples,test,testing}/**/*.ts\"",
32
+ "test": "tsx --test test/*.test.ts",
33
+ "example-setup": "tsx examples/shared/setup-governance.ts",
34
+ "example-client": "tsx examples/client/anthropic.ts",
35
+ "example-client-anthropic": "tsx examples/client/anthropic.ts",
36
+ "example-client-openai": "tsx examples/client/openai.ts",
37
+ "example-client-gemini": "tsx examples/client/gemini.ts",
38
+ "example-client-groq": "tsx examples/client/groq.ts",
39
+ "example-client-mistral": "tsx examples/client/mistral.ts",
40
+ "example-client-ollama": "tsx examples/client/ollama.ts",
41
+ "example-client-openrouter": "tsx examples/client/openrouter.ts",
42
+ "example-client-litellm": "tsx examples/client/litellm.ts",
43
+ "example-client-typesafe": "tsx examples/client/typesafe.ts",
44
+ "example-two-agents": "tsx examples/client/two-agents.ts",
45
+ "example-gateway": "tsx examples/gateway/openrouter.ts",
46
+ "example-gateway-openrouter": "tsx examples/gateway/openrouter.ts",
47
+ "example-gateway-litellm": "tsx examples/gateway/litellm.ts",
48
+ "example-gateway-bedrock": "tsx examples/gateway/bedrock.ts"
49
+ },
50
+ "nx": {
51
+ "includedScripts": [
52
+ "build",
53
+ "lint",
54
+ "test"
55
+ ]
56
+ },
57
+ "files": [
58
+ "dist/**/*"
59
+ ],
60
+ "engines": {
61
+ "node": ">=22"
62
+ },
63
+ "dependencies": {
64
+ "@stigg/node-server-sdk": "6.1.0",
65
+ "@stigg/typescript": "0.1.0-beta.55",
66
+ "zod": "^4.6.1"
67
+ },
68
+ "devDependencies": {
69
+ "@anthropic-ai/sdk": "^0.124.0",
70
+ "@aws-sdk/client-bedrock-runtime": "^3.1150.0",
71
+ "@google/genai": "^2.28.0",
72
+ "@mistralai/mistralai": "^2.7.0",
73
+ "@openrouter/sdk": "^1.4.25",
74
+ "@typesafe-ai/sdk": "^0.6.0",
75
+ "dotenv": "^17.4.2",
76
+ "groq-sdk": "^1.6.0",
77
+ "ollama": "^0.6.4",
78
+ "openai": "^7.13.0",
79
+ "tsx": "^4.23.13"
80
+ },
81
+ "exports": {
82
+ ".": {
83
+ "types": "./dist/index.d.ts",
84
+ "default": "./dist/index.js"
85
+ },
86
+ "./internal": {
87
+ "types": "./dist/internal.d.ts",
88
+ "default": "./dist/internal.js"
89
+ },
90
+ "./package.json": "./package.json"
91
+ }
6
92
  }