pilotswarm-sdk 0.5.47 → 0.5.49

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 (48) hide show
  1. package/api/src/http-api-transport.js +11 -0
  2. package/api/src/protocol.js +1 -0
  3. package/dist/cms-migrations.d.ts.map +1 -1
  4. package/dist/cms-migrations.js +440 -0
  5. package/dist/cms-migrations.js.map +1 -1
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +4 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/management-client.d.ts +87 -0
  11. package/dist/management-client.d.ts.map +1 -1
  12. package/dist/management-client.js +62 -5
  13. package/dist/management-client.js.map +1 -1
  14. package/dist/model-providers.d.ts +36 -5
  15. package/dist/model-providers.d.ts.map +1 -1
  16. package/dist/model-providers.js +41 -6
  17. package/dist/model-providers.js.map +1 -1
  18. package/dist/provider-catalog.d.ts.map +1 -1
  19. package/dist/provider-catalog.js +58 -10
  20. package/dist/provider-catalog.js.map +1 -1
  21. package/dist/provider-store.d.ts +45 -1
  22. package/dist/provider-store.d.ts.map +1 -1
  23. package/dist/provider-store.js +62 -2
  24. package/dist/provider-store.js.map +1 -1
  25. package/dist/provider-tools.d.ts +8 -0
  26. package/dist/provider-tools.d.ts.map +1 -1
  27. package/dist/provider-tools.js +39 -1
  28. package/dist/provider-tools.js.map +1 -1
  29. package/dist/session-manager.d.ts.map +1 -1
  30. package/dist/session-manager.js +28 -5
  31. package/dist/session-manager.js.map +1 -1
  32. package/dist/session-proxy.d.ts.map +1 -1
  33. package/dist/session-proxy.js +9 -5
  34. package/dist/session-proxy.js.map +1 -1
  35. package/dist/web/generated-op-methods.d.ts +8 -0
  36. package/dist/web/generated-op-methods.d.ts.map +1 -1
  37. package/dist/web/generated-op-methods.js +2 -0
  38. package/dist/web/generated-op-methods.js.map +1 -1
  39. package/dist/web/web-management-client.d.ts +4 -0
  40. package/dist/web/web-management-client.d.ts.map +1 -1
  41. package/dist/web/web-management-client.js +7 -0
  42. package/dist/web/web-management-client.js.map +1 -1
  43. package/dist/wif-credentials.d.ts +181 -0
  44. package/dist/wif-credentials.d.ts.map +1 -0
  45. package/dist/wif-credentials.js +382 -0
  46. package/dist/wif-credentials.js.map +1 -0
  47. package/package.json +3 -3
  48. package/plugins/mgmt/agents/token-manager.agent.md +1 -0
@@ -22,7 +22,7 @@ import { resolveStorageConfig } from "./storage-config.js";
22
22
  import { getDuroxideStorageProvider, getRuntimeStorageProvider } from "./storage-providers.js";
23
23
  import { SessionDumper } from "./session-dumper.js";
24
24
  import { computeSessionFootprint, FootprintCache } from "./footprint.js";
25
- import { loadModelProviders, loadModelProviderTypes } from "./model-providers.js";
25
+ import { loadModelProviders, loadModelProviderTypes, providerTypeUsesWorkloadIdentity } from "./model-providers.js";
26
26
  import { bootstrapProviders, resolveProviderCredential, resolveRuntimeModelSelection } from "./provider-catalog.js";
27
27
  import { deriveStatusFromCmsAndRuntime, shouldSyncCompletedStatus, shouldSyncFailedStatus } from "./session-status.js";
28
28
  import { assertUnambiguousProvider, isWebOptions } from "./web/api-connection.js";
@@ -2509,6 +2509,33 @@ export class PilotSwarmManagementClient {
2509
2509
  throw new ProviderError("PROVIDER_INVALID", `No provider type named "${wanted}" on this deployment. `
2510
2510
  + `It has ${known.slice(0, 6).join(", ")}${known.length > 6 ? ", …" : ""}.`);
2511
2511
  }
2512
+ /**
2513
+ * Does this type authenticate as the worker rather than with a key?
2514
+ *
2515
+ * The store knows a type only by its name, so the decision is made here,
2516
+ * where the type catalog is. An unknown type answers false and is refused
2517
+ * a moment later by `_assertKnownProviderType` — this is not the place
2518
+ * that reports it.
2519
+ */
2520
+ _typeUsesWorkloadIdentity(typeId) {
2521
+ const wanted = String(typeId ?? "").trim();
2522
+ const group = this.getModelsByProvider().find((candidate) => candidate.providerId === wanted);
2523
+ return providerTypeUsesWorkloadIdentity(group?.type);
2524
+ }
2525
+ /**
2526
+ * Refuse a key update on a provider that has no key.
2527
+ *
2528
+ * Accepting it would store a real secret in a row nothing ever reads a
2529
+ * secret from, and tell the person their rotation worked.
2530
+ */
2531
+ async _assertCredentialIsUpdatable(store, name, actor, isAdmin) {
2532
+ const rows = await store.listProviders(actor, isAdmin);
2533
+ const row = rows.find((candidate) => candidate.name === name);
2534
+ if (row && this._typeUsesWorkloadIdentity(row.typeId)) {
2535
+ throw new ProviderError("PROVIDER_INVALID", `Provider "${name}" authenticates with the worker's workload identity and has no key to update. `
2536
+ + "Change the worker's identity configuration instead.");
2537
+ }
2538
+ }
2512
2539
  async createProvider(viewer, input) {
2513
2540
  const { store, actor, isAdmin } = await this._providerActor(viewer);
2514
2541
  this._assertKnownProviderType(input.type);
@@ -2518,6 +2545,7 @@ export class PilotSwarmManagementClient {
2518
2545
  class: "shared",
2519
2546
  secretRef: input.credentials ?? null,
2520
2547
  baseUrl: input.baseUrl ?? null,
2548
+ workloadIdentity: this._typeUsesWorkloadIdentity(input.type),
2521
2549
  }, actor, isAdmin);
2522
2550
  await this._auditProviderMutation(viewer, "createProvider", created.name, { class: "shared", type: created.typeId });
2523
2551
  // A name that did not resolve a moment ago now does.
@@ -2531,6 +2559,15 @@ export class PilotSwarmManagementClient {
2531
2559
  throw new ProviderError("PROVIDER_FORBIDDEN", "Sign in to add a personal provider.");
2532
2560
  }
2533
2561
  this._assertKnownProviderType(input.type);
2562
+ // A personal provider exists to run on ITS OWNER'S credentials. This
2563
+ // type has none: it runs on the worker's, which is the organization's.
2564
+ // A personal one would spend the cluster's own account under a name no
2565
+ // administrator can cap, hold or delete, because a personal provider
2566
+ // answers only to its owner — and anyone signed in may create one.
2567
+ if (this._typeUsesWorkloadIdentity(input.type)) {
2568
+ throw new ProviderError("PROVIDER_FORBIDDEN", `Provider type "${input.type}" authenticates with the worker's own identity, `
2569
+ + "so it cannot be a personal provider. An administrator can add it as a shared one.");
2570
+ }
2534
2571
  const created = await store.createProvider({
2535
2572
  name: input.name,
2536
2573
  typeId: input.type,
@@ -2545,7 +2582,8 @@ export class PilotSwarmManagementClient {
2545
2582
  }
2546
2583
  /** Replace the credential on one of the caller's own personal providers. */
2547
2584
  async updateMyProviderCredential(viewer, input) {
2548
- const { store, actor } = await this._providerActor(viewer);
2585
+ const { store, actor, isAdmin } = await this._providerActor(viewer);
2586
+ await this._assertCredentialIsUpdatable(store, input.name, actor, isAdmin);
2549
2587
  const updated = await store.updatePersonalCredential(input.name, input.credentials, actor);
2550
2588
  await this._auditProviderMutation(viewer, "updateMyProviderCredential", updated.name, {
2551
2589
  class: "personal",
@@ -2563,6 +2601,7 @@ export class PilotSwarmManagementClient {
2563
2601
  */
2564
2602
  async updateSharedProviderCredential(viewer, input) {
2565
2603
  const { store, actor, isAdmin } = await this._providerActor(viewer);
2604
+ await this._assertCredentialIsUpdatable(store, input.name, actor, isAdmin);
2566
2605
  const updated = await store.updateSharedCredential(input.name, input.credentials, actor, isAdmin);
2567
2606
  await this._auditProviderMutation(viewer, "updateSharedProviderCredential", updated.name, {
2568
2607
  class: "shared",
@@ -2993,6 +3032,18 @@ export class PilotSwarmManagementClient {
2993
3032
  truncated: breakdown.length > limit,
2994
3033
  };
2995
3034
  }
3035
+ /**
3036
+ * The cluster summary: totals for today / the week / the month, a per-day
3037
+ * series and the per-model pivot, over every provider (or the ones named).
3038
+ * Read from the ledger, so system sessions are in it — unlike the meters
3039
+ * the Providers tab reads, which count people's turns only.
3040
+ */
3041
+ async getProviderUsageSummary(viewer, query = {}) {
3042
+ const { store, actor, isAdmin } = await this._providerActor(viewer);
3043
+ const days = clampInteger(query.days ?? undefined, 14, 1, 365);
3044
+ const providers = Array.isArray(query.providers) ? query.providers : null;
3045
+ return await store.usageSummary(actor, isAdmin, days, providers);
3046
+ }
2996
3047
  /** Sessions waiting on a limit right now, with what is holding each one. */
2997
3048
  async listPausedSessions(viewer) {
2998
3049
  const { store, actor, isAdmin } = await this._providerActor(viewer);
@@ -3394,9 +3445,15 @@ export class PilotSwarmManagementClient {
3394
3445
  qualifiedName: descriptor.qualifiedName,
3395
3446
  providerId: descriptor.providerId,
3396
3447
  providerType: descriptor.providerType,
3397
- credentialAvailable: resolved.type === "github"
3398
- ? Boolean(resolved.githubToken)
3399
- : Boolean(resolved.sdkProvider?.apiKey),
3448
+ // A workload-identity provider has a credential in every sense
3449
+ // that matters here — the worker can authenticate — it just is
3450
+ // not a stored one. Testing for a key would grey out the model in
3451
+ // every picker and refuse it as a default.
3452
+ credentialAvailable: resolved.usesWorkloadIdentity
3453
+ ? true
3454
+ : resolved.type === "github"
3455
+ ? Boolean(resolved.githubToken)
3456
+ : Boolean(resolved.sdkProvider?.apiKey),
3400
3457
  };
3401
3458
  }
3402
3459
  // ─── Session Dump ────────────────────────────────────────