@puku-ai/sdk 4.0.3 → 4.0.4

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 (199) hide show
  1. package/README.md +24 -7
  2. package/dist/index.cjs +85 -0
  3. package/dist/vendor/_vendor/partial-json-parser/parser.cjs +225 -0
  4. package/dist/vendor/api-promise.cjs +18 -0
  5. package/dist/vendor/client.cjs +1013 -0
  6. package/dist/vendor/core/api-promise.cjs +80 -0
  7. package/dist/vendor/core/api.cjs +2 -0
  8. package/dist/vendor/core/credentials.cjs +313 -0
  9. package/dist/vendor/core/error.cjs +156 -0
  10. package/dist/vendor/core/middleware.cjs +173 -0
  11. package/dist/vendor/core/pagination.cjs +215 -0
  12. package/dist/vendor/core/resource.cjs +11 -0
  13. package/dist/vendor/core/streaming.cjs +346 -0
  14. package/dist/vendor/core/uploads.cjs +5 -0
  15. package/dist/vendor/error.cjs +18 -0
  16. package/dist/vendor/helpers/beta/environments.cjs +30 -0
  17. package/dist/vendor/helpers/beta/json-schema.cjs +56 -0
  18. package/dist/vendor/helpers/beta/mcp.cjs +418 -0
  19. package/dist/vendor/helpers/beta/memory.cjs +17 -0
  20. package/dist/vendor/helpers/beta/standard-schema.cjs +57 -0
  21. package/dist/vendor/helpers/beta/zod.cjs +88 -0
  22. package/dist/vendor/helpers/index.cjs +7 -0
  23. package/dist/vendor/helpers/json-schema.cjs +36 -0
  24. package/dist/vendor/helpers/zod.cjs +77 -0
  25. package/dist/vendor/index.cjs +54 -0
  26. package/dist/vendor/internal/builtin-types.cjs +3 -0
  27. package/dist/vendor/internal/constants.cjs +12 -0
  28. package/dist/vendor/internal/decoders/jsonl.cjs +40 -0
  29. package/dist/vendor/internal/decoders/line.cjs +109 -0
  30. package/dist/vendor/internal/detect-platform.cjs +159 -0
  31. package/dist/vendor/internal/errors.cjs +42 -0
  32. package/dist/vendor/internal/file-store.cjs +535 -0
  33. package/dist/vendor/internal/headers.cjs +119 -0
  34. package/dist/vendor/internal/message-stream-utils.cjs +33 -0
  35. package/dist/vendor/internal/node.browser.cjs +21 -0
  36. package/dist/vendor/internal/node.cjs +55 -0
  37. package/dist/vendor/internal/parse.cjs +65 -0
  38. package/dist/vendor/internal/qs/formats.cjs +12 -0
  39. package/dist/vendor/internal/qs/index.cjs +13 -0
  40. package/dist/vendor/internal/qs/stringify.cjs +276 -0
  41. package/dist/vendor/internal/qs/types.cjs +2 -0
  42. package/dist/vendor/internal/qs/utils.cjs +229 -0
  43. package/dist/vendor/internal/request-options.cjs +31 -0
  44. package/dist/vendor/internal/request-signal.cjs +49 -0
  45. package/dist/vendor/internal/shim-types.cjs +3 -0
  46. package/dist/vendor/internal/shims.cjs +91 -0
  47. package/dist/vendor/internal/stainless-helper-header.cjs +90 -0
  48. package/dist/vendor/internal/stream-utils.cjs +37 -0
  49. package/dist/vendor/internal/to-file.cjs +95 -0
  50. package/dist/vendor/internal/types.cjs +3 -0
  51. package/dist/vendor/internal/uploads.cjs +148 -0
  52. package/dist/vendor/internal/utils/abort.cjs +24 -0
  53. package/dist/vendor/internal/utils/async-queue.cjs +69 -0
  54. package/dist/vendor/internal/utils/backoff.cjs +43 -0
  55. package/dist/vendor/internal/utils/base64.cjs +37 -0
  56. package/dist/vendor/internal/utils/bytes.cjs +30 -0
  57. package/dist/vendor/internal/utils/env.cjs +21 -0
  58. package/dist/vendor/internal/utils/log.cjs +111 -0
  59. package/dist/vendor/internal/utils/path.cjs +78 -0
  60. package/dist/vendor/internal/utils/promise.cjs +17 -0
  61. package/dist/vendor/internal/utils/query.cjs +41 -0
  62. package/dist/vendor/internal/utils/sleep.cjs +27 -0
  63. package/dist/vendor/internal/utils/time.cjs +7 -0
  64. package/dist/vendor/internal/utils/uuid.cjs +18 -0
  65. package/dist/vendor/internal/utils/values.cjs +125 -0
  66. package/dist/vendor/internal/utils.cjs +24 -0
  67. package/dist/vendor/lib/BetaMessageStream.cjs +665 -0
  68. package/dist/vendor/lib/MessageStream.cjs +612 -0
  69. package/dist/vendor/lib/beta-parser.cjs +78 -0
  70. package/dist/vendor/lib/credentials/credential-chain.cjs +244 -0
  71. package/dist/vendor/lib/credentials/identity-token.cjs +71 -0
  72. package/dist/vendor/lib/credentials/oidc-federation.cjs +81 -0
  73. package/dist/vendor/lib/credentials/token-cache.cjs +113 -0
  74. package/dist/vendor/lib/credentials/types.cjs +267 -0
  75. package/dist/vendor/lib/credentials/user-oauth.cjs +129 -0
  76. package/dist/vendor/lib/credentials.cjs +7 -0
  77. package/dist/vendor/lib/environments/index.cjs +17 -0
  78. package/dist/vendor/lib/environments/poller.cjs +226 -0
  79. package/dist/vendor/lib/environments/worker.cjs +609 -0
  80. package/dist/vendor/lib/helper-client.cjs +57 -0
  81. package/dist/vendor/lib/middleware.cjs +779 -0
  82. package/dist/vendor/lib/parser.cjs +65 -0
  83. package/dist/vendor/lib/sessions/accumulate.cjs +44 -0
  84. package/dist/vendor/lib/standard-schema.cjs +44 -0
  85. package/dist/vendor/lib/tools/BetaRunnableTool.cjs +30 -0
  86. package/dist/vendor/lib/tools/BetaToolRunner.cjs +500 -0
  87. package/dist/vendor/lib/tools/CompactionControl.cjs +27 -0
  88. package/dist/vendor/lib/tools/SessionToolRunner.cjs +740 -0
  89. package/dist/vendor/lib/tools/ToolError.cjs +46 -0
  90. package/dist/vendor/lib/transform-json-schema.cjs +113 -0
  91. package/dist/vendor/pagination.cjs +18 -0
  92. package/dist/vendor/resource.cjs +18 -0
  93. package/dist/vendor/resources/beta/agents/agents.cjs +159 -0
  94. package/dist/vendor/resources/beta/agents/index.cjs +8 -0
  95. package/dist/vendor/resources/beta/agents/versions.cjs +35 -0
  96. package/dist/vendor/resources/beta/agents.cjs +18 -0
  97. package/dist/vendor/resources/beta/beta.cjs +105 -0
  98. package/dist/vendor/resources/beta/deployment-runs.cjs +54 -0
  99. package/dist/vendor/resources/beta/deployments.cjs +195 -0
  100. package/dist/vendor/resources/beta/dreams.cjs +115 -0
  101. package/dist/vendor/resources/beta/environments/environments.cjs +178 -0
  102. package/dist/vendor/resources/beta/environments/index.cjs +8 -0
  103. package/dist/vendor/resources/beta/environments/work.cjs +256 -0
  104. package/dist/vendor/resources/beta/environments.cjs +18 -0
  105. package/dist/vendor/resources/beta/files.cjs +123 -0
  106. package/dist/vendor/resources/beta/index.cjs +38 -0
  107. package/dist/vendor/resources/beta/memory-stores/index.cjs +10 -0
  108. package/dist/vendor/resources/beta/memory-stores/memories.cjs +129 -0
  109. package/dist/vendor/resources/beta/memory-stores/memory-stores.cjs +173 -0
  110. package/dist/vendor/resources/beta/memory-stores/memory-versions.cjs +80 -0
  111. package/dist/vendor/resources/beta/memory-stores.cjs +18 -0
  112. package/dist/vendor/resources/beta/messages/batches.cjs +206 -0
  113. package/dist/vendor/resources/beta/messages/index.cjs +11 -0
  114. package/dist/vendor/resources/beta/messages/messages.cjs +189 -0
  115. package/dist/vendor/resources/beta/messages.cjs +18 -0
  116. package/dist/vendor/resources/beta/models.cjs +59 -0
  117. package/dist/vendor/resources/beta/organization/api-keys.cjs +55 -0
  118. package/dist/vendor/resources/beta/organization/compliance-settings.cjs +51 -0
  119. package/dist/vendor/resources/beta/organization/external-keys.cjs +118 -0
  120. package/dist/vendor/resources/beta/organization/federation/federation.cjs +49 -0
  121. package/dist/vendor/resources/beta/organization/federation/index.cjs +10 -0
  122. package/dist/vendor/resources/beta/organization/federation/issuers.cjs +168 -0
  123. package/dist/vendor/resources/beta/organization/federation/rules/index.cjs +8 -0
  124. package/dist/vendor/resources/beta/organization/federation/rules/rules.cjs +226 -0
  125. package/dist/vendor/resources/beta/organization/federation/rules/workspaces.cjs +113 -0
  126. package/dist/vendor/resources/beta/organization/federation/rules.cjs +18 -0
  127. package/dist/vendor/resources/beta/organization/federation.cjs +18 -0
  128. package/dist/vendor/resources/beta/organization/index.cjs +24 -0
  129. package/dist/vendor/resources/beta/organization/invites.cjs +75 -0
  130. package/dist/vendor/resources/beta/organization/organization.cjs +90 -0
  131. package/dist/vendor/resources/beta/organization/rate-limits.cjs +30 -0
  132. package/dist/vendor/resources/beta/organization/service-accounts/index.cjs +8 -0
  133. package/dist/vendor/resources/beta/organization/service-accounts/service-accounts.cjs +202 -0
  134. package/dist/vendor/resources/beta/organization/service-accounts/workspaces.cjs +124 -0
  135. package/dist/vendor/resources/beta/organization/service-accounts.cjs +18 -0
  136. package/dist/vendor/resources/beta/organization/users.cjs +66 -0
  137. package/dist/vendor/resources/beta/organization/workspaces/index.cjs +12 -0
  138. package/dist/vendor/resources/beta/organization/workspaces/members.cjs +101 -0
  139. package/dist/vendor/resources/beta/organization/workspaces/rate-limits.cjs +33 -0
  140. package/dist/vendor/resources/beta/organization/workspaces/service-accounts.cjs +188 -0
  141. package/dist/vendor/resources/beta/organization/workspaces/workspaces.cjs +140 -0
  142. package/dist/vendor/resources/beta/organization/workspaces.cjs +18 -0
  143. package/dist/vendor/resources/beta/organization.cjs +18 -0
  144. package/dist/vendor/resources/beta/sessions/events.cjs +119 -0
  145. package/dist/vendor/resources/beta/sessions/index.cjs +12 -0
  146. package/dist/vendor/resources/beta/sessions/resources.cjs +131 -0
  147. package/dist/vendor/resources/beta/sessions/sessions.cjs +186 -0
  148. package/dist/vendor/resources/beta/sessions/threads/events.cjs +60 -0
  149. package/dist/vendor/resources/beta/sessions/threads/index.cjs +8 -0
  150. package/dist/vendor/resources/beta/sessions/threads/threads.cjs +116 -0
  151. package/dist/vendor/resources/beta/sessions/threads.cjs +18 -0
  152. package/dist/vendor/resources/beta/sessions.cjs +18 -0
  153. package/dist/vendor/resources/beta/skills/index.cjs +8 -0
  154. package/dist/vendor/resources/beta/skills/skills.cjs +132 -0
  155. package/dist/vendor/resources/beta/skills/versions.cjs +128 -0
  156. package/dist/vendor/resources/beta/skills.cjs +18 -0
  157. package/dist/vendor/resources/beta/tunnels/certificates.cjs +128 -0
  158. package/dist/vendor/resources/beta/tunnels/index.cjs +8 -0
  159. package/dist/vendor/resources/beta/tunnels/tunnels.cjs +209 -0
  160. package/dist/vendor/resources/beta/tunnels.cjs +18 -0
  161. package/dist/vendor/resources/beta/user-profiles.cjs +117 -0
  162. package/dist/vendor/resources/beta/vaults/credentials.cjs +176 -0
  163. package/dist/vendor/resources/beta/vaults/index.cjs +8 -0
  164. package/dist/vendor/resources/beta/vaults/vaults.cjs +177 -0
  165. package/dist/vendor/resources/beta/vaults.cjs +18 -0
  166. package/dist/vendor/resources/beta/webhooks.cjs +32 -0
  167. package/dist/vendor/resources/beta.cjs +18 -0
  168. package/dist/vendor/resources/completions.cjs +22 -0
  169. package/dist/vendor/resources/files.cjs +51 -0
  170. package/dist/vendor/resources/index.cjs +31 -0
  171. package/dist/vendor/resources/messages/batches.cjs +160 -0
  172. package/dist/vendor/resources/messages/index.cjs +8 -0
  173. package/dist/vendor/resources/messages/messages.cjs +159 -0
  174. package/dist/vendor/resources/messages.cjs +18 -0
  175. package/dist/vendor/resources/models.cjs +44 -0
  176. package/dist/vendor/resources/shared.cjs +3 -0
  177. package/dist/vendor/resources/skills/index.cjs +8 -0
  178. package/dist/vendor/resources/skills/skills.cjs +72 -0
  179. package/dist/vendor/resources/skills/versions.cjs +40 -0
  180. package/dist/vendor/resources/skills.cjs +18 -0
  181. package/dist/vendor/resources/top-level.cjs +3 -0
  182. package/dist/vendor/resources.cjs +17 -0
  183. package/dist/vendor/streaming.cjs +18 -0
  184. package/dist/vendor/tools/agent-toolset/fs-util.cjs +193 -0
  185. package/dist/vendor/tools/agent-toolset/memories.cjs +916 -0
  186. package/dist/vendor/tools/agent-toolset/node.browser.cjs +147 -0
  187. package/dist/vendor/tools/agent-toolset/node.cjs +939 -0
  188. package/dist/vendor/tools/agent-toolset/skills.cjs +325 -0
  189. package/dist/vendor/tools/agent-toolset/sync-interval.cjs +28 -0
  190. package/dist/vendor/tools/memory/node.browser.cjs +48 -0
  191. package/dist/vendor/tools/memory/node.cjs +364 -0
  192. package/dist/vendor/uploads.cjs +18 -0
  193. package/dist/vendor/version.cjs +4 -0
  194. package/package.json +12 -13
  195. package/sdk.cjs +0 -14271
  196. package/sdk.cjs.map +0 -149
  197. package/sdk.d.ts +0 -10866
  198. package/sdk.mjs +0 -68
  199. package/sdk.mjs.map +0 -149
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WorkloadIdentityError = exports.ADVISORY_REFRESH_BACKOFF_IN_SECONDS = exports.MANDATORY_REFRESH_THRESHOLD_IN_SECONDS = exports.ADVISORY_REFRESH_THRESHOLD_IN_SECONDS = exports.FEDERATION_BETA_HEADER = exports.OAUTH_API_BETA_HEADER = exports.TOKEN_ENDPOINT = exports.GRANT_TYPE_REFRESH_TOKEN = exports.GRANT_TYPE_JWT_BEARER = void 0;
37
+ exports.requireSecureTokenEndpoint = requireSecureTokenEndpoint;
38
+ exports.parseTokenResponse = parseTokenResponse;
39
+ exports.redactSensitive = redactSensitive;
40
+ exports.checkCredentialsFileSafety = checkCredentialsFileSafety;
41
+ exports.writeCredentialsFileAtomic = writeCredentialsFileAtomic;
42
+ const error_1 = require("../../core/error");
43
+ exports.GRANT_TYPE_JWT_BEARER = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
44
+ exports.GRANT_TYPE_REFRESH_TOKEN = 'refresh_token';
45
+ exports.TOKEN_ENDPOINT = '/v1/oauth/token';
46
+ /**
47
+ * `puku-beta` value required on authenticated API requests using an
48
+ * OAuth bearer token, and on `refresh_token` grants against the token endpoint.
49
+ */
50
+ exports.OAUTH_API_BETA_HEADER = 'oauth-2025-04-20';
51
+ /**
52
+ * `puku-beta` value required on jwt-bearer exchanges against the token
53
+ * endpoint. It routes the request to the federation service; it must NOT be
54
+ * sent on `refresh_token` grants, which are handled by a different backend.
55
+ */
56
+ exports.FEDERATION_BETA_HEADER = 'oidc-federation-2026-04-01';
57
+ exports.ADVISORY_REFRESH_THRESHOLD_IN_SECONDS = 120;
58
+ exports.MANDATORY_REFRESH_THRESHOLD_IN_SECONDS = 30;
59
+ exports.ADVISORY_REFRESH_BACKOFF_IN_SECONDS = 5;
60
+ const MAX_TOKEN_RESPONSE_BYTES = 1 << 20;
61
+ /**
62
+ * Rejects base URLs that would cause a JWT assertion or refresh token to be
63
+ * sent over cleartext HTTP. Loopback hosts are allowed for local development.
64
+ */
65
+ function requireSecureTokenEndpoint(baseURL) {
66
+ if (!baseURL)
67
+ return;
68
+ let u;
69
+ try {
70
+ u = new URL(baseURL);
71
+ }
72
+ catch (err) {
73
+ throw new WorkloadIdentityError(`Invalid token endpoint base URL "${baseURL}": ${err}`);
74
+ }
75
+ if (u.protocol === 'https:')
76
+ return;
77
+ // WHATWG URL.hostname returns bracketed IPv6 ("[::1]"); Go's net/url strips them.
78
+ const host = u.hostname.toLowerCase().replace(/^\[|\]$/g, '');
79
+ if (u.protocol === 'http:' && (host === 'localhost' || host === '127.0.0.1' || host === '::1')) {
80
+ return;
81
+ }
82
+ throw new WorkloadIdentityError(`Refusing to send credential over non-https token endpoint "${baseURL}"`);
83
+ }
84
+ /**
85
+ * Reads the response body as text, parses it as a token-endpoint JSON
86
+ * response, validates `access_token` is present, and rejects a non-Bearer
87
+ * `token_type` when one is provided. Reads at most
88
+ * {@link MAX_TOKEN_RESPONSE_BYTES} from the body stream.
89
+ */
90
+ async function parseTokenResponse(resp, requestId) {
91
+ const text = await readLimitedText(resp);
92
+ let data;
93
+ try {
94
+ data = JSON.parse(text);
95
+ }
96
+ catch {
97
+ throw new WorkloadIdentityError(`Token endpoint returned non-JSON response (status ${resp.status})`, resp.status, redactSensitive(text), requestId);
98
+ }
99
+ if (!data.access_token) {
100
+ throw new WorkloadIdentityError(`Token endpoint response missing access_token: ${JSON.stringify(redactSensitive(data))}`, resp.status, redactSensitive(data), requestId);
101
+ }
102
+ if (data.token_type && data.token_type.toLowerCase() !== 'bearer') {
103
+ throw new WorkloadIdentityError(`Token endpoint response: unsupported token_type "${data.token_type}" (want Bearer)`, resp.status, redactSensitive(data), requestId);
104
+ }
105
+ return data;
106
+ }
107
+ const MAX_ERROR_BODY_CHARS = 2000;
108
+ // RFC 6749 §5.2 standard error-response fields. Anything else in a token
109
+ // endpoint error body is potentially echoed input (assertion, refresh_token,
110
+ // access_token, …) and is dropped rather than allowlisted-with-exceptions.
111
+ const SAFE_ERROR_KEYS = new Set(['error', 'error_description', 'error_uri']);
112
+ /**
113
+ * Returns a redacted copy of a token-endpoint error body for safe inclusion
114
+ * in an exception. Strings are truncated; objects keep only the RFC 6749
115
+ * §5.2 error fields.
116
+ */
117
+ function redactSensitive(body) {
118
+ if (body == null)
119
+ return body;
120
+ if (typeof body === 'string') {
121
+ let parsed;
122
+ try {
123
+ parsed = JSON.parse(body);
124
+ }
125
+ catch {
126
+ if (body.length <= MAX_ERROR_BODY_CHARS)
127
+ return body;
128
+ return body.slice(0, MAX_ERROR_BODY_CHARS) + `... <${body.length - MAX_ERROR_BODY_CHARS} more chars>`;
129
+ }
130
+ return JSON.stringify(redactSensitive(parsed));
131
+ }
132
+ if (typeof body === 'object' && !Array.isArray(body)) {
133
+ const out = {};
134
+ for (const [k, v] of Object.entries(body)) {
135
+ if (SAFE_ERROR_KEYS.has(k))
136
+ out[k] = v;
137
+ }
138
+ return out;
139
+ }
140
+ return null;
141
+ }
142
+ /**
143
+ * Best-effort safety check on a credentials file before reading it.
144
+ *
145
+ * On POSIX: resolves symlinks (so containerized deployments that mount the
146
+ * credential as a symlink to a tmpfs-backed file keep working), then rejects
147
+ * the resolved target if it is group- or world- readable or writable. A uid
148
+ * mismatch on the resolved target is surfaced via `onWarn` since
149
+ * root-written/app-read is common in init-container setups. No-op on Windows.
150
+ */
151
+ async function checkCredentialsFileSafety(path, onWarn = (m) => console.warn(`puku-ai/sdk: ${m}`)) {
152
+ if (typeof process === 'undefined' || process.platform === 'win32')
153
+ return;
154
+ const { fs } = await Promise.resolve().then(() => __importStar(require('../../internal/node')));
155
+ let resolved = path;
156
+ let st;
157
+ try {
158
+ resolved = await fs.promises.realpath(path);
159
+ st = await fs.promises.stat(resolved);
160
+ }
161
+ catch {
162
+ return; // ENOENT etc — let the subsequent read surface a precise error
163
+ }
164
+ const mode = st.mode & 0o777;
165
+ // 0o022 = group/world write; 0o044 = group/world read.
166
+ if (mode & 0o022) {
167
+ throw new WorkloadIdentityError(`Credentials file at ${resolved} is group/world-writable (mode 0o${mode.toString(8)}); ` +
168
+ `this allows other local users to plant tokens. Run \`chmod 600 ${resolved}\`.`);
169
+ }
170
+ if (mode & 0o044) {
171
+ throw new WorkloadIdentityError(`Credentials file at ${resolved} is group/world-readable (mode 0o${mode.toString(8)}); ` +
172
+ `run \`chmod 600 ${resolved}\` before retrying.`);
173
+ }
174
+ if (typeof process.getuid === 'function' && st.uid !== process.getuid()) {
175
+ onWarn(`credentials file at ${resolved} is owned by uid ${st.uid} (current process uid ${process.getuid()}); ` + `verify this is intentional.`);
176
+ }
177
+ }
178
+ /**
179
+ * Atomically writes JSON to `targetPath` via a `.tmp` sibling + rename,
180
+ * with fsync on the file and (best-effort) on the parent directory.
181
+ * Creates the parent directory with mode 0700 and the file with mode 0600.
182
+ */
183
+ async function writeCredentialsFileAtomic(targetPath, data) {
184
+ const { fs, path } = await Promise.resolve().then(() => __importStar(require('../../internal/node')));
185
+ const dir = path.dirname(targetPath);
186
+ await fs.promises.mkdir(dir, { recursive: true, mode: 0o700 });
187
+ // Unique temp name avoids two concurrent writers (different processes or
188
+ // SDK instances) racing on the same '.tmp' sibling and corrupting each
189
+ // other's bytes mid-write before the rename.
190
+ const tmpPath = `${targetPath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
191
+ try {
192
+ const fh = await fs.promises.open(tmpPath, 'w', 0o600);
193
+ try {
194
+ await fh.writeFile(JSON.stringify(data, null, 2));
195
+ await fh.sync();
196
+ }
197
+ finally {
198
+ await fh.close();
199
+ }
200
+ await fs.promises.rename(tmpPath, targetPath);
201
+ }
202
+ catch (err) {
203
+ // Don't leak the temp file if anything between create and rename failed.
204
+ await fs.promises.unlink(tmpPath).catch(() => { });
205
+ throw err;
206
+ }
207
+ // fsync the parent directory so the rename survives a crash.
208
+ try {
209
+ const dirFh = await fs.promises.open(dir, 'r');
210
+ try {
211
+ await dirFh.sync();
212
+ }
213
+ finally {
214
+ await dirFh.close();
215
+ }
216
+ }
217
+ catch {
218
+ // Directory fsync is best-effort (unsupported on some platforms, e.g. Windows).
219
+ }
220
+ }
221
+ async function readLimitedText(resp) {
222
+ if (!resp.body) {
223
+ return '';
224
+ }
225
+ const reader = resp.body.getReader();
226
+ const chunks = [];
227
+ let received = 0;
228
+ for (;;) {
229
+ const { done, value } = await reader.read();
230
+ if (done)
231
+ break;
232
+ if (received + value.length > MAX_TOKEN_RESPONSE_BYTES) {
233
+ const remaining = MAX_TOKEN_RESPONSE_BYTES - received;
234
+ if (remaining > 0)
235
+ chunks.push(value.subarray(0, remaining));
236
+ await reader.cancel();
237
+ break;
238
+ }
239
+ chunks.push(value);
240
+ received += value.length;
241
+ }
242
+ let merged;
243
+ if (chunks.length === 1) {
244
+ merged = chunks[0];
245
+ }
246
+ else {
247
+ merged = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));
248
+ let offset = 0;
249
+ for (const c of chunks) {
250
+ merged.set(c, offset);
251
+ offset += c.length;
252
+ }
253
+ }
254
+ return new TextDecoder('utf-8').decode(merged);
255
+ }
256
+ class WorkloadIdentityError extends error_1.PukuError {
257
+ statusCode;
258
+ body;
259
+ requestId;
260
+ constructor(message, statusCode = null, body = null, requestId = null) {
261
+ super(message);
262
+ this.statusCode = statusCode;
263
+ this.body = body;
264
+ this.requestId = requestId;
265
+ }
266
+ }
267
+ exports.WorkloadIdentityError = WorkloadIdentityError;
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.userOAuthProvider = userOAuthProvider;
37
+ const credentials_1 = require("../../core/credentials");
38
+ const types_1 = require("./types");
39
+ const time_1 = require("../../internal/utils/time");
40
+ const version_1 = require("../../version");
41
+ /**
42
+ * Reads a user-oauth credential file. Returns the cached access token while
43
+ * fresh; on expiry performs a `refresh_token` grant and writes the new
44
+ * tokens back to the credentials file (atomic replace, fsync'd).
45
+ *
46
+ * If `clientId` is empty, the access token is treated as static — the
47
+ * credentials file is read on every call but no refresh is attempted, and
48
+ * an expired token without a `refresh_token` raises.
49
+ */
50
+ function userOAuthProvider(config) {
51
+ return async (opts) => {
52
+ const { fs } = await Promise.resolve().then(() => __importStar(require('../../internal/node')));
53
+ await (0, types_1.checkCredentialsFileSafety)(config.credentialsPath, config.onSafetyWarning);
54
+ let raw;
55
+ try {
56
+ raw = await fs.promises.readFile(config.credentialsPath, 'utf-8');
57
+ }
58
+ catch (err) {
59
+ throw new types_1.WorkloadIdentityError(`Credentials file not found at ${config.credentialsPath}: ${err}`);
60
+ }
61
+ let creds;
62
+ try {
63
+ creds = JSON.parse(raw);
64
+ }
65
+ catch (err) {
66
+ throw new types_1.WorkloadIdentityError(`Credentials file at ${config.credentialsPath} is not valid JSON: ${err}`);
67
+ }
68
+ const accessToken = creds.access_token;
69
+ if (!accessToken) {
70
+ throw new types_1.WorkloadIdentityError(`Credentials file at ${config.credentialsPath} must include 'access_token'`);
71
+ }
72
+ // Return cached token if still fresh (or no expiry info), unless the
73
+ // caller is forcing a refresh after a 401 — then go straight to refresh
74
+ // even if the file's expires_at still looks valid.
75
+ const expiresAt = creds.expires_at;
76
+ if (!opts?.forceRefresh &&
77
+ (expiresAt == null || (0, time_1.nowAsSeconds)() < expiresAt - types_1.MANDATORY_REFRESH_THRESHOLD_IN_SECONDS)) {
78
+ return { token: accessToken, expiresAt: expiresAt ?? null };
79
+ }
80
+ const refreshToken = creds.refresh_token;
81
+ if (!config.clientId || !refreshToken) {
82
+ throw new types_1.WorkloadIdentityError(`Access token at ${config.credentialsPath} has expired and no refresh is available ` +
83
+ `(client_id ${config.clientId ? 'set' : 'empty'}, refresh_token ${refreshToken ? 'set' : 'empty'})`);
84
+ }
85
+ (0, types_1.requireSecureTokenEndpoint)(config.baseURL);
86
+ const body = {
87
+ grant_type: types_1.GRANT_TYPE_REFRESH_TOKEN,
88
+ refresh_token: refreshToken,
89
+ client_id: config.clientId,
90
+ };
91
+ const url = `${config.baseURL}${types_1.TOKEN_ENDPOINT}`;
92
+ let resp;
93
+ try {
94
+ resp = await config.fetch(url, {
95
+ method: 'POST',
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ 'puku-beta': types_1.OAUTH_API_BETA_HEADER,
99
+ 'User-Agent': config.userAgent || `puku-ai-sdk-typescript/${version_1.VERSION} userOAuthProvider`,
100
+ },
101
+ body: JSON.stringify(body),
102
+ });
103
+ }
104
+ catch (err) {
105
+ throw new types_1.WorkloadIdentityError(`User OAuth refresh failed to reach token endpoint: ${err}`);
106
+ }
107
+ const requestId = resp.headers.get('Request-Id');
108
+ if (!resp.ok) {
109
+ const text = await resp.text().catch(() => '');
110
+ throw new types_1.WorkloadIdentityError(`User OAuth refresh failed (HTTP ${resp.status}): ${(0, types_1.redactSensitive)(text)}`, resp.status, (0, types_1.redactSensitive)(text), requestId);
111
+ }
112
+ const data = await (0, types_1.parseTokenResponse)(resp, requestId);
113
+ const expiresIn = Number(data.expires_in);
114
+ if (!Number.isFinite(expiresIn)) {
115
+ throw new types_1.WorkloadIdentityError(`User OAuth refresh response missing or invalid expires_in: ${JSON.stringify((0, types_1.redactSensitive)(data))}`, resp.status, (0, types_1.redactSensitive)(data), requestId);
116
+ }
117
+ const newExpiresAt = (0, time_1.nowAsSeconds)() + expiresIn;
118
+ const newRefreshToken = data.refresh_token || refreshToken;
119
+ await (0, types_1.writeCredentialsFileAtomic)(config.credentialsPath, {
120
+ ...creds,
121
+ version: credentials_1.CREDENTIALS_FILE_VERSION,
122
+ type: 'oauth_token',
123
+ access_token: data.access_token,
124
+ expires_at: newExpiresAt,
125
+ refresh_token: newRefreshToken,
126
+ });
127
+ return { token: data.access_token, expiresAt: newExpiresAt };
128
+ };
129
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveCredentialsFromConfig = exports.loadConfig = void 0;
4
+ var credentials_1 = require("../core/credentials");
5
+ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return credentials_1.loadConfig; } });
6
+ var credential_chain_1 = require("./credentials/credential-chain");
7
+ Object.defineProperty(exports, "resolveCredentialsFromConfig", { enumerable: true, get: function () { return credential_chain_1.resolveCredentialsFromConfig; } });
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_MAX_IDLE_MS = exports.MANAGED_AGENTS_BETA = exports.SessionToolRunner = exports.EnvironmentWorker = exports.isFatal4xx = exports.is4xx = exports.isStatus = exports.jitter = exports.backoff = exports.POLL_BLOCK_MS = exports.WorkPoller = void 0;
4
+ var poller_1 = require("./poller");
5
+ Object.defineProperty(exports, "WorkPoller", { enumerable: true, get: function () { return poller_1.WorkPoller; } });
6
+ Object.defineProperty(exports, "POLL_BLOCK_MS", { enumerable: true, get: function () { return poller_1.POLL_BLOCK_MS; } });
7
+ Object.defineProperty(exports, "backoff", { enumerable: true, get: function () { return poller_1.backoff; } });
8
+ Object.defineProperty(exports, "jitter", { enumerable: true, get: function () { return poller_1.jitter; } });
9
+ Object.defineProperty(exports, "isStatus", { enumerable: true, get: function () { return poller_1.isStatus; } });
10
+ Object.defineProperty(exports, "is4xx", { enumerable: true, get: function () { return poller_1.is4xx; } });
11
+ Object.defineProperty(exports, "isFatal4xx", { enumerable: true, get: function () { return poller_1.isFatal4xx; } });
12
+ var worker_1 = require("./worker");
13
+ Object.defineProperty(exports, "EnvironmentWorker", { enumerable: true, get: function () { return worker_1.EnvironmentWorker; } });
14
+ var SessionToolRunner_1 = require("../tools/SessionToolRunner");
15
+ Object.defineProperty(exports, "SessionToolRunner", { enumerable: true, get: function () { return SessionToolRunner_1.SessionToolRunner; } });
16
+ Object.defineProperty(exports, "MANAGED_AGENTS_BETA", { enumerable: true, get: function () { return SessionToolRunner_1.MANAGED_AGENTS_BETA; } });
17
+ Object.defineProperty(exports, "DEFAULT_MAX_IDLE_MS", { enumerable: true, get: function () { return SessionToolRunner_1.DEFAULT_MAX_IDLE_MS; } });
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkPoller = exports.POLL_BLOCK_MS = exports.jitter = exports.isStatus = exports.isFatal4xx = exports.is4xx = void 0;
4
+ exports.backoff = backoff;
5
+ const error_1 = require("../../core/error");
6
+ const log_1 = require("../../internal/utils/log");
7
+ const sleep_1 = require("../../internal/utils/sleep");
8
+ const uuid_1 = require("../../internal/utils/uuid");
9
+ const abort_1 = require("../../internal/utils/abort");
10
+ const headers_1 = require("../../internal/headers");
11
+ const backoff_1 = require("../../internal/utils/backoff");
12
+ const helper_client_1 = require("../helper-client");
13
+ var backoff_2 = require("../../internal/utils/backoff");
14
+ Object.defineProperty(exports, "is4xx", { enumerable: true, get: function () { return backoff_2.is4xx; } });
15
+ Object.defineProperty(exports, "isFatal4xx", { enumerable: true, get: function () { return backoff_2.isFatal4xx; } });
16
+ Object.defineProperty(exports, "isStatus", { enumerable: true, get: function () { return backoff_2.isStatus; } });
17
+ Object.defineProperty(exports, "jitter", { enumerable: true, get: function () { return backoff_2.jitter; } });
18
+ // API caps block_ms at 999; rely on client-side jitter between empty polls.
19
+ exports.POLL_BLOCK_MS = 999;
20
+ const POLL_BACKOFF_BASE_MS = 1000;
21
+ const POLL_BACKOFF_CAP_MS = 60_000;
22
+ const IDLE_REPORT_INTERVAL_MS = 300_000;
23
+ /**
24
+ * Async-iterable that long-polls a self-hosted environment for work, ack's
25
+ * each item, yields the {@link BetaSelfHostedWork} item, and posts `stop` after
26
+ * the consumer's loop body returns (or when the consumer `break`s).
27
+ *
28
+ * A yielded item may carry a per-item `secret` payload (populated only by the
29
+ * poll response); the poller passes it through untouched — consumers such as
30
+ * {@link EnvironmentWorker} extract the sessions token it carries and prefer
31
+ * that over the environment key for the item's downstream calls. Treat it as
32
+ * opaque and never log it.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * for await (const work of client.beta.environments.work.poller({
37
+ * environmentId,
38
+ * environmentKey,
39
+ * })) {
40
+ * // ...service the work...
41
+ * }
42
+ * ```
43
+ */
44
+ class WorkPoller {
45
+ client;
46
+ environmentId;
47
+ environmentKey;
48
+ workerId;
49
+ // Sub-client scoped to the environment key. Every poll / ack / stop call
50
+ // is routed through this so the parent's `X-Api-Key` never lands on the
51
+ // wire alongside the bearer credential. The helper-telemetry header is
52
+ // attached as a default on this client; per-call plumbing is unnecessary.
53
+ #runnerClient;
54
+ #consumed = false;
55
+ #controller;
56
+ #detachExternal;
57
+ #autoStop;
58
+ #drain;
59
+ #blockMs;
60
+ #reclaimOlderThanMs;
61
+ #requestOpts;
62
+ constructor(opts) {
63
+ this.client = opts.client;
64
+ this.environmentId = opts.environmentId;
65
+ this.environmentKey = opts.environmentKey;
66
+ this.workerId = opts.workerId ?? defaultWorkerId();
67
+ this.#runnerClient = (0, helper_client_1.copyClientForHelper)(opts.client, {
68
+ authToken: opts.environmentKey,
69
+ helper: 'environments-work-poller',
70
+ });
71
+ this.#autoStop = opts.autoStop ?? true;
72
+ this.#drain = opts.drain ?? false;
73
+ // `undefined` => default to the API cap; an explicit `null` => omit
74
+ // `block_ms` for a non-blocking poll.
75
+ this.#blockMs = opts.blockMs === undefined ? exports.POLL_BLOCK_MS : opts.blockMs;
76
+ this.#reclaimOlderThanMs = opts.reclaimOlderThanMs ?? null;
77
+ this.#requestOpts = opts.requestOptions;
78
+ this.#controller = new AbortController();
79
+ this.#detachExternal = (0, abort_1.linkAbort)(opts.signal, this.#controller);
80
+ }
81
+ /** Read-only view of this iterator's abort signal. */
82
+ get signal() {
83
+ return this.#controller.signal;
84
+ }
85
+ /** Abort the iterator. The current `for await` will exit cleanly. */
86
+ abort() {
87
+ this.#controller.abort();
88
+ }
89
+ async *[Symbol.asyncIterator]() {
90
+ if (this.#consumed) {
91
+ throw new error_1.PukuError('Cannot iterate over a consumed WorkPoller');
92
+ }
93
+ this.#consumed = true;
94
+ const log = (0, log_1.loggerFor)(this.client);
95
+ log.info('poller starting', {
96
+ component: 'work-poller',
97
+ environment_id: this.environmentId,
98
+ });
99
+ const idle = new IdleLog(log, this.environmentId);
100
+ try {
101
+ let attempt = 0;
102
+ while (!this.#controller.signal.aborted) {
103
+ let work;
104
+ try {
105
+ work = await this.#runnerClient.beta.environments.work.poll(this.environmentId, {
106
+ 'PukuAI-Worker-ID': this.workerId,
107
+ ...(this.#blockMs !== null ? { block_ms: this.#blockMs } : {}),
108
+ ...(this.#reclaimOlderThanMs !== null ?
109
+ { reclaim_older_than_ms: this.#reclaimOlderThanMs }
110
+ : {}),
111
+ }, { headers: (0, headers_1.buildHeaders)([this.#requestOpts?.headers]), signal: this.#controller.signal });
112
+ }
113
+ catch (e) {
114
+ if (this.#controller.signal.aborted)
115
+ return;
116
+ // A bad environment key / missing environment never recovers — surface
117
+ // it instead of spinning forever at the backoff cap.
118
+ if ((0, backoff_1.isFatal4xx)(e)) {
119
+ log.error('poll failed permanently, stopping poller', { error: String(e) });
120
+ throw e;
121
+ }
122
+ // Jittered exponential backoff so a fleet of pollers doesn't retry in
123
+ // lockstep after a shared outage.
124
+ const wait = (0, backoff_1.applyJitter)(backoff(attempt));
125
+ log.warn('poll failed, backing off', { error: String(e), backoff_ms: wait });
126
+ attempt++;
127
+ await (0, sleep_1.sleep)(wait, this.#controller.signal);
128
+ continue;
129
+ }
130
+ attempt = 0;
131
+ if (work == null) {
132
+ // Queue empty: either return now (drain) or wait and poll again.
133
+ if (this.#drain)
134
+ return;
135
+ idle.onEmptyPoll();
136
+ await (0, sleep_1.sleep)((0, backoff_1.jitter)(1000, 3000), this.#controller.signal);
137
+ continue;
138
+ }
139
+ idle.onClaim();
140
+ log.info('claimed work', {
141
+ component: 'work-poller',
142
+ environment_id: this.environmentId,
143
+ work_id: work.id,
144
+ work_type: work.data.type,
145
+ });
146
+ try {
147
+ await this.#runnerClient.beta.environments.work.ack(work.id, { environment_id: work.environment_id }, { headers: (0, headers_1.buildHeaders)([this.#requestOpts?.headers]), signal: this.#controller.signal });
148
+ }
149
+ catch (e) {
150
+ log.error('ack failed', { work_id: work.id, error: String(e) });
151
+ continue;
152
+ }
153
+ try {
154
+ yield work;
155
+ }
156
+ finally {
157
+ // Post-handler stop. Runs whether the consumer body returned
158
+ // normally, threw, or `break`d out of the loop — unless the consumer
159
+ // owns the stop itself (`autoStop: false`).
160
+ if (this.#autoStop) {
161
+ try {
162
+ await this.#runnerClient.beta.environments.work.stop(work.id, { environment_id: work.environment_id }, { headers: (0, headers_1.buildHeaders)([this.#requestOpts?.headers]) });
163
+ }
164
+ catch (e) {
165
+ if (!(0, backoff_1.isStatus)(e, 409))
166
+ log.warn('stop failed', { work_id: work.id, error: String(e) });
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+ finally {
173
+ // Detach from the external signal so the consumer can drop their
174
+ // signal reference without leaking this iterator instance.
175
+ this.#detachExternal();
176
+ }
177
+ }
178
+ }
179
+ exports.WorkPoller = WorkPoller;
180
+ /** Exponential poll backoff: 1s, 2s, 4s … clamped to a 60s cap. */
181
+ function backoff(attempt) {
182
+ return (0, backoff_1.backoff)(attempt, POLL_BACKOFF_BASE_MS, POLL_BACKOFF_CAP_MS);
183
+ }
184
+ /**
185
+ * Keeps an idle poll loop visible in the logs without an INFO line per poll:
186
+ * the first empty poll after start-up or after a claim logs at INFO and later
187
+ * ones at DEBUG, with an INFO reminder every `IDLE_REPORT_INTERVAL_MS` while
188
+ * the loop stays idle.
189
+ */
190
+ class IdleLog {
191
+ #log;
192
+ #environmentId;
193
+ #idleSince;
194
+ #lastReport = 0;
195
+ constructor(log, environmentId) {
196
+ this.#log = log;
197
+ this.#environmentId = environmentId;
198
+ }
199
+ onEmptyPoll() {
200
+ const now = Date.now();
201
+ const fields = { component: 'work-poller', environment_id: this.#environmentId };
202
+ if (this.#idleSince === undefined) {
203
+ this.#idleSince = this.#lastReport = now;
204
+ this.#log.info('idle; polling for work', fields);
205
+ }
206
+ else if (now - this.#lastReport >= IDLE_REPORT_INTERVAL_MS) {
207
+ this.#lastReport = now;
208
+ this.#log.info(`still polling; idle for ${Math.round((now - this.#idleSince) / 1000)}s`, fields);
209
+ }
210
+ else {
211
+ this.#log.debug('poll returned no work', fields);
212
+ }
213
+ }
214
+ onClaim() {
215
+ this.#idleSince = undefined;
216
+ }
217
+ }
218
+ function defaultWorkerId() {
219
+ // The API documents the worker id as a *unique* identifier for Redis consumer
220
+ // groups, so the fallback must be unique even when several pollers share a
221
+ // host. Prefix with the hostname when one is exposed for readability, but rely
222
+ // on the uuid for uniqueness.
223
+ const env = globalThis.process?.env;
224
+ const host = env?.['HOSTNAME'];
225
+ return host ? `${host}-${(0, uuid_1.uuid4)()}` : (0, uuid_1.uuid4)();
226
+ }