@superatomai/sdk-node 0.0.56-dsp → 0.0.57-dsp

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/dist/index.d.ts CHANGED
@@ -254,6 +254,12 @@ interface ScriptQueryResult {
254
254
  * sentinel toolId so the frontend resolves it via the queryCache short-circuit.
255
255
  */
256
256
  virtual?: boolean;
257
+ /**
258
+ * Restrictions an authorization policy injected into THIS query before it
259
+ * ran. Handed to getAnalysis/getComponents as `scope` so the answer can name
260
+ * the restriction without the recipe hardcoding a value that goes stale.
261
+ */
262
+ appliedPolicies?: string[];
257
263
  }
258
264
  /**
259
265
  * Match tier returned by the LLM script matcher.
@@ -514,6 +520,13 @@ interface ExecutedToolInfo {
514
520
  _summary?: any;
515
521
  /** Up to MAIN_AGENT_COMPLETE_ROWS rows — the complete result when small. */
516
522
  _mainAgentRows?: any[];
523
+ /**
524
+ * Set when an authorization policy restricted the query before it ran.
525
+ * Read by BOTH agents: the source agent's tool response and the main
526
+ * agent's result block, because the main agent is the one that writes the
527
+ * titles, analysis and method line that must state the restriction.
528
+ */
529
+ _ACCESS_POLICY_APPLIED?: string;
517
530
  };
518
531
  /**
519
532
  * THIS call's rows, at render size — deliberately a sibling of `result`, not a
@@ -2867,6 +2880,22 @@ declare class ScriptStore {
2867
2880
  * specs, a stale spec array beside a live program is how the wrong one gets
2868
2881
  * read later. See backend/docs/COMPONENTS-AS-PROGRAM-DESIGN.md § 4.4.
2869
2882
  */
2883
+ /**
2884
+ * Body text as it stands now, for reverting an attach that turns out to be
2885
+ * invalid.
2886
+ *
2887
+ * getComponents can only be VALIDATED by running it, and it can only be run
2888
+ * once it is on disk — so attachComponents necessarily writes before anyone
2889
+ * knows whether the body is good. Without a revert, a rejected body stays
2890
+ * attached: promote() then sees the recipe "exports getComponents", clears
2891
+ * the specs the fallback generator produced, and the recipe is verified with
2892
+ * component code that was already rejected. Confirmed live on
2893
+ * "Total Bookings by Branch", which shipped a sourceRef of 'computed:_final'
2894
+ * that validateSpecs had refused.
2895
+ */
2896
+ snapshotBody(recipeId: string): Promise<string | null>;
2897
+ /** Put back a body captured by {@link snapshotBody}. */
2898
+ restoreBody(recipeId: string, body: string): Promise<boolean>;
2870
2899
  attachComponents(recipeId: string, componentsBody: string): Promise<boolean>;
2871
2900
  /**
2872
2901
  * Append (or replace) the `getAnalysis` export on an existing draft body.
@@ -3028,6 +3057,14 @@ declare class MainAgent {
3028
3057
  * is never trusted because it is a program, exactly as an authored spec is not.
3029
3058
  */
3030
3059
  private handleWriteComponents;
3060
+ /**
3061
+ * Restrictions the seam reported while this run's queries executed.
3062
+ *
3063
+ * getData does NOT re-run for write_components/write_analysis, so the child
3064
+ * cannot observe these itself — the parent hands them across, exactly as it
3065
+ * does for `entities`.
3066
+ */
3067
+ private observedPolicies;
3031
3068
  /**
3032
3069
  * Author the answer as a program. Runs after execute_script, so the body is
3033
3070
  * written with the result already known and can react to what it found.
@@ -4430,6 +4467,15 @@ declare class QueryCache {
4430
4467
  * Get the current TTL in minutes
4431
4468
  */
4432
4469
  getTTL(): number;
4470
+ /**
4471
+ * Which access bucket this call reads and writes.
4472
+ *
4473
+ * `''` means the unrestricted bucket and produces a key identical to the one
4474
+ * used before authorization existed. `null` means do not touch the cache.
4475
+ */
4476
+ private scope;
4477
+ /** The stored key: the scope namespace, then the caller's key. NUL cannot occur in SQL. */
4478
+ private scopedKey;
4433
4479
  /**
4434
4480
  * Store query result in data cache.
4435
4481
  * If the key already exists, it's removed first so the re-insert places it
@@ -4500,6 +4546,246 @@ declare class QueryCache {
4500
4546
  }
4501
4547
  declare const queryCache: QueryCache;
4502
4548
 
4549
+ /**
4550
+ * Request context — who is asking, carried to wherever it is needed.
4551
+ *
4552
+ * The data seam (`BaseSource.prepareSql()` in the backend) has to know which
4553
+ * user a query is for, so the SQL rewriter has a policy to inject. Identity
4554
+ * arrives here, in the SDK's message handlers; the seam is several layers and
4555
+ * one package away. This module is the carrier for the paths where the async
4556
+ * chain stays intact.
4557
+ *
4558
+ * Design and the paths where it does NOT reach:
4559
+ * backend/docs/REQUEST-CONTEXT-DESIGN.md
4560
+ *
4561
+ * Two rules the rest of the system depends on:
4562
+ *
4563
+ * 1. **Absence is not `system`.** No context means we do not know who is
4564
+ * asking, which is a different thing from knowing this is a trusted job.
4565
+ * Conflating them turns every call site anyone forgets into an unpoliced
4566
+ * one. Trust has to be written down, by name, via `runAsSystem()`.
4567
+ *
4568
+ * 2. **This is not a security boundary on its own.** It carries whatever it
4569
+ * is given. It is only worth something once the value it carries comes
4570
+ * from a verified identity rather than the request payload — see the
4571
+ * Prerequisite section of SQL-AUTHORIZATION-DESIGN.md.
4572
+ */
4573
+ /**
4574
+ * Who a unit of work is running on behalf of.
4575
+ *
4576
+ * `system` requires a reason because it appears in the audit log and because
4577
+ * an unexplained escalation is indistinguishable from a bug.
4578
+ */
4579
+ type Principal = {
4580
+ kind: 'user';
4581
+ userId: string;
4582
+ orgId?: string;
4583
+ role?: string;
4584
+ } | {
4585
+ kind: 'system';
4586
+ reason: string;
4587
+ };
4588
+ /**
4589
+ * One row restriction, in the shape the rewriter's inject_policies() consumes
4590
+ * directly — no translation layer, deliberately: a mapping step between what an
4591
+ * admin writes and what gets injected is somewhere for the two to drift apart.
4592
+ */
4593
+ interface RowFilter {
4594
+ /** Unqualified matches on table name alone; qualified ("dw.FactSales") must match exactly. */
4595
+ table?: string;
4596
+ column: string;
4597
+ op?: 'in' | 'not_in' | 'eq' | 'ne';
4598
+ values: unknown[];
4599
+ /**
4600
+ * How to SAY this restriction to an end user, e.g. "Hyderabad branch".
4601
+ *
4602
+ * Without it the agent has only the predicate, and pastes
4603
+ * `com_trn_documentstamp.LocationId IN (110)` into the answer — accurate and
4604
+ * meaningless to the person reading it. Only whoever writes the policy knows
4605
+ * that 110 is Hyderabad, so only they can supply this.
4606
+ */
4607
+ label?: string;
4608
+ }
4609
+ /**
4610
+ * What one user may see in one source. `sourceId` is not optional in spirit: a
4611
+ * filter naming a column of one database must never be injected into another's
4612
+ * SQL. Omitting it means "every source", which is only correct for a column that
4613
+ * genuinely exists everywhere.
4614
+ */
4615
+ interface SourcePolicy {
4616
+ sourceId?: string | null;
4617
+ /** Default {@link RowFilter.label} for every filter in this policy that lacks its own. */
4618
+ label?: string;
4619
+ rowFilters?: RowFilter[];
4620
+ /** Gate 3. Empty means no table restriction — see SQL-AUTHORIZATION-DESIGN.md. */
4621
+ readableTables?: string[];
4622
+ }
4623
+ interface RequestContext {
4624
+ principal: Principal;
4625
+ projectId?: string;
4626
+ /**
4627
+ * Access policies resolved ONCE per request, not per query. Empty means
4628
+ * "no restrictions apply". Narrowed to the source being queried at the seam
4629
+ * — see the backend's policy-gate.
4630
+ */
4631
+ policies?: SourcePolicy[];
4632
+ /** Correlates the audit log with a chat turn. */
4633
+ requestId?: string;
4634
+ }
4635
+ /** The context for the current async chain, or `undefined` if none was established. */
4636
+ declare function getRequestContext(): RequestContext | undefined;
4637
+ /**
4638
+ * Like `getRequestContext()`, but throws when there is none.
4639
+ *
4640
+ * For call sites that must not proceed anonymously. Prefer this over
4641
+ * `getRequestContext() ?? somethingPermissive` — the fallback is exactly the
4642
+ * silent bypass this module exists to prevent.
4643
+ */
4644
+ declare function requireRequestContext(what?: string): RequestContext;
4645
+ declare class MissingRequestContextError extends Error {
4646
+ constructor(message: string);
4647
+ }
4648
+ /** Run `fn` with `ctx` visible to everything it awaits. */
4649
+ declare function runWithContext<T>(ctx: RequestContext, fn: () => T): T;
4650
+ /** Convenience for the common case: a request on behalf of a signed-in user. */
4651
+ declare function runAsUser<T>(user: {
4652
+ userId: string;
4653
+ orgId?: string;
4654
+ role?: string;
4655
+ projectId?: string;
4656
+ requestId?: string;
4657
+ policies?: SourcePolicy[];
4658
+ }, fn: () => T): T;
4659
+ /**
4660
+ * Declare a unit of work as trusted, naming why.
4661
+ *
4662
+ * For entry points with no user behind them: schedulers, admin tooling, the
4663
+ * cross-machine proxy. `reason` is not decoration — it is what the audit log
4664
+ * shows in place of a user, and it is what makes these paths greppable when
4665
+ * someone asks "what runs unpoliced?".
4666
+ *
4667
+ * Nesting inside a user context deliberately REPLACES it: a system subtask is
4668
+ * an escalation, and it should look like one in the log rather than silently
4669
+ * inheriting a user's restrictions.
4670
+ */
4671
+ declare function runAsSystem<T>(reason: string, fn: () => T, opts?: {
4672
+ projectId?: string;
4673
+ requestId?: string;
4674
+ }): T;
4675
+ /**
4676
+ * Capture the current context so it can be re-entered later.
4677
+ *
4678
+ * For boundaries where the async chain breaks but a reference survives — an
4679
+ * event listener registered outside the request, a callback stored in a
4680
+ * registry. Does NOT help across a process or HTTP boundary (the script
4681
+ * bridge); that needs a token, see the design doc.
4682
+ */
4683
+ declare function captureContext(): RequestContext | undefined;
4684
+ /** Re-enter a captured context. A no-op wrapper when `ctx` is undefined. */
4685
+ declare function withCapturedContext<T>(ctx: RequestContext | undefined, fn: () => T): T;
4686
+ /**
4687
+ * Bind a function to the context active at bind time.
4688
+ *
4689
+ * The trap this exists for, stated the right way round (verified, because it
4690
+ * is easy to get backwards): context propagates through ASYNC RESOURCE
4691
+ * creation, and `EventEmitter.emit` is an ordinary synchronous call. So a
4692
+ * plain listener runs in the context active at EMIT time, whatever it was
4693
+ * registered inside. A handler registered during a request and fired later
4694
+ * from another chain therefore sees nothing at all.
4695
+ *
4696
+ * Bind it when the registering context is the one that matters.
4697
+ */
4698
+ declare function bindContext<A extends unknown[], R>(fn: (...args: A) => R): (...args: A) => R;
4699
+ /** Short label for logs and audit rows: `user:u_123` / `system:alert-scheduler` / `anonymous`. */
4700
+ declare function describeContext(ctx?: RequestContext | undefined): string;
4701
+ /** True when the context represents a signed-in user rather than a trusted job. */
4702
+ declare function isUserContext(ctx?: RequestContext | undefined): boolean;
4703
+
4704
+ /**
4705
+ * Deriving "who is asking" from an incoming WebSocket message.
4706
+ *
4707
+ * Separate from `utils/request-context.ts` on purpose: that module is a pure
4708
+ * carrier with no opinion about where identity comes from, this one knows the
4709
+ * message shape and the trust level of each field.
4710
+ *
4711
+ * See backend/docs/REQUEST-CONTEXT-DESIGN.md and the Prerequisite section of
4712
+ * backend/docs/SQL-AUTHORIZATION-DESIGN.md.
4713
+ */
4714
+
4715
+ /**
4716
+ * Read access policies out of the admin-authored per-user config.
4717
+ *
4718
+ * The config is free-form JSON typed by a human into an admin field, so every
4719
+ * step here is defensive: a malformed entry is DROPPED, never guessed at. That
4720
+ * is a deliberate trade-off with a sharp edge — a typo'd policy silently
4721
+ * becomes no policy, i.e. unrestricted. Validating shapes against the source
4722
+ * schema (and refusing, rather than dropping) is the fix, and is not built yet.
4723
+ *
4724
+ * Accepts either a single object or an array, so one user can be scoped across
4725
+ * several sources.
4726
+ */
4727
+ declare function policiesFromConfig(config: unknown): SourcePolicy[];
4728
+ /**
4729
+ * Run `fn` with the caller's identity established.
4730
+ *
4731
+ * Trust order:
4732
+ *
4733
+ * 1. `message.authContext` — stamped by the relay from a verified session.
4734
+ * Trustworthy. Does not exist yet.
4735
+ * 2. `payload.userId` — sent by the browser, which can put anything there.
4736
+ * Enough to prove the plumbing works end to end; NOT enough to enforce
4737
+ * anything on. Used because it is what exists today.
4738
+ * 3. Neither — no context is established at all.
4739
+ *
4740
+ * Case 3 is deliberately not a `system` context. "We don't know who this is"
4741
+ * and "this is a trusted job" must stay distinguishable, or every path that
4742
+ * loses identity silently becomes an unpoliced one. With no context, the data
4743
+ * seam decides what to do (see SA_SQL_POLICY_ENFORCE), and the honest answer
4744
+ * there is a refusal rather than an unfiltered read.
4745
+ */
4746
+ declare function runWithMessageIdentity<T>(message: any, fn: () => T): T;
4747
+
4748
+ /**
4749
+ * Context tokens — carrying identity across a boundary AsyncLocalStorage cannot.
4750
+ *
4751
+ * The script flow is the one path where the async chain genuinely breaks:
4752
+ * scripts run in a separate OS process and call back into the backend over
4753
+ * loopback HTTP (`script-bootstrap.ts` → `script-bridge.ts`), so the bridge's
4754
+ * request handler starts a fresh async context with no relationship to the
4755
+ * chat turn that launched the script. Nothing ambient crosses that; the
4756
+ * identity has to be handed over explicitly.
4757
+ *
4758
+ * So: the parent mints a token bound to the live context before spawning, the
4759
+ * child presents it on every bridge call, and the bridge resolves it back and
4760
+ * runs the query inside that context.
4761
+ *
4762
+ * The registry is in-memory and process-local, which is exactly right here —
4763
+ * the minting side (script-runner) and the resolving side (script-bridge) are
4764
+ * both in the backend process; only the script itself is elsewhere. A token is
4765
+ * therefore never valid anywhere but the process that issued it, and never
4766
+ * outlives that process.
4767
+ *
4768
+ * See backend/docs/REQUEST-CONTEXT-DESIGN.md.
4769
+ */
4770
+
4771
+ /**
4772
+ * Mint a token for the context active right now.
4773
+ *
4774
+ * Returns `undefined` when there is no context — deliberately, so that an
4775
+ * unidentified script run stays unidentified rather than being handed a token
4776
+ * that vouches for nothing. The bridge then sees no token and the data seam
4777
+ * treats it as anonymous, which is the truth.
4778
+ */
4779
+ declare function mintContextToken(ttlMs?: number): string | undefined;
4780
+ /** Resolve a token back to its context, or `undefined` if unknown or expired. */
4781
+ declare function resolveContextToken(token: string | undefined | null): RequestContext | undefined;
4782
+ /** Drop a token. Call when the work it was minted for is finished. */
4783
+ declare function revokeContextToken(token: string | undefined | null): void;
4784
+ /** Diagnostics only. */
4785
+ declare function contextTokenCount(): number;
4786
+ /** Test seam. */
4787
+ declare function clearContextTokens(): void;
4788
+
4503
4789
  /**
4504
4790
  * Manages conversation history scoped per user + dashboard.
4505
4791
  * Each user-dashboard pair has its own isolated history that expires after a configurable TTL.
@@ -5375,6 +5661,17 @@ interface RunScriptOptions {
5375
5661
  * subsidiary's name" from being a reason to rewrite getData and re-query.
5376
5662
  */
5377
5663
  entities?: ResolvedEntityRef[];
5664
+ /**
5665
+ * Restrictions an authorization policy imposed on this run, handed to
5666
+ * getAnalysis/getComponents as their 6th argument.
5667
+ *
5668
+ * Supplied at RUN time rather than written into the recipe: a policy is
5669
+ * per-request and mutable, a recipe is durable. Baked in, it goes stale the
5670
+ * moment the user's scope changes — the recipe would keep naming the old
5671
+ * scope while the seam injects the new one. Supplied here, a replay always
5672
+ * describes what was actually applied to THAT run.
5673
+ */
5674
+ appliedPolicies?: string[];
5378
5675
  }
5379
5676
  /**
5380
5677
  * Execute a recipe by spawning a tsx child on the script's .ts file.
@@ -5585,4 +5882,4 @@ declare class SuperatomSDK {
5585
5882
  getConversationSimilarityThreshold(): number;
5586
5883
  }
5587
5884
 
5588
- export { type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type CollectionHandler, type CollectionOperation, type DBUIBlock, DEFAULT_AGENT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type Harness, type HybridSearchOptions, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, type ModelStrategy, type OutputContract, type OutputField, type OutputValidator, type RerankedResult, type RunAgentOptions, STORAGE_CONFIG, type ScriptComponentSpec, ScriptMatcher, type ScriptParameter, type ScriptRecipe, type ScriptRecipeMetaRow, type ScriptRecipeStore, type ScriptResult, ScriptStore, type ScriptStoreOptions, type SelectedWorkflow, SuperatomSDK, type SuperatomSDKConfig, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type WorkflowDescriptor, type Workspace, anthropicLLM, assertReadOnlySql, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeTriggers, emitAgentEvent, extractNamedExport, geminiLLM, getCodingAgent, getCodingAgentsConfig, groqLLM, hybridRerank, listCodingAgents, llmUsageLogger, logger, normalizeScriptBody, onAgentRun, openaiLLM, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, rerankChromaResults, rerankConversationResults, resolveScriptRecipeStore, runCodingAgent, runScript, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, writeBridgeShims };
5885
+ export { type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type CollectionHandler, type CollectionOperation, type DBUIBlock, DEFAULT_AGENT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type Harness, type HybridSearchOptions, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, type OutputContract, type OutputField, type OutputValidator, type Principal, type RequestContext, type RerankedResult, type RowFilter, type RunAgentOptions, STORAGE_CONFIG, type ScriptComponentSpec, ScriptMatcher, type ScriptParameter, type ScriptRecipe, type ScriptRecipeMetaRow, type ScriptRecipeStore, type ScriptResult, ScriptStore, type ScriptStoreOptions, type SelectedWorkflow, type SourcePolicy, SuperatomSDK, type SuperatomSDKConfig, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type WorkflowDescriptor, type Workspace, anthropicLLM, assertReadOnlySql, bindContext, captureContext, clearContextTokens, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, geminiLLM, getCodingAgent, getCodingAgentsConfig, getRequestContext, groqLLM, hybridRerank, isUserContext, listCodingAgents, llmUsageLogger, logger, mintContextToken, normalizeScriptBody, onAgentRun, openaiLLM, policiesFromConfig, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, withCapturedContext, writeBridgeShims };