@superatomai/sdk-node 0.0.87-dsp → 0.0.89-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.mts +90 -22
- package/dist/index.d.ts +90 -22
- package/dist/index.js +202 -36
- package/dist/index.mjs +201 -36
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
|
@@ -4480,6 +4480,56 @@ interface SourcePolicy {
|
|
|
4480
4480
|
/** Grants outside the scope above. Empty or absent means none. */
|
|
4481
4481
|
exceptions?: PolicyException[];
|
|
4482
4482
|
}
|
|
4483
|
+
/**
|
|
4484
|
+
* Operators the constraint engine builds predicates from. A superset of
|
|
4485
|
+
* {@link RowFilter.op}, which the original rewriter is limited to.
|
|
4486
|
+
*/
|
|
4487
|
+
type ConstraintOp = 'in' | 'not_in' | 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'not_like' | 'is_null' | 'is_not_null';
|
|
4488
|
+
/**
|
|
4489
|
+
* One filter in a {@link ConstraintPolicy}.
|
|
4490
|
+
*
|
|
4491
|
+
* No `table`, unlike {@link RowFilter}: these are keyed by table, so a filter
|
|
4492
|
+
* cannot fail to match the table it was written for and leave it unfiltered.
|
|
4493
|
+
*/
|
|
4494
|
+
interface ConstraintFilter {
|
|
4495
|
+
column: string;
|
|
4496
|
+
op?: ConstraintOp;
|
|
4497
|
+
/** Omitted only for `is_null` / `is_not_null`. */
|
|
4498
|
+
values?: unknown[];
|
|
4499
|
+
label?: string;
|
|
4500
|
+
}
|
|
4501
|
+
/**
|
|
4502
|
+
* What one user may see in one source, in the shape the constraint engine reads
|
|
4503
|
+
* (`sqlrewrite/v2/engine.py`).
|
|
4504
|
+
*
|
|
4505
|
+
* Not a superset of {@link SourcePolicy} but a different shape: it adds
|
|
4506
|
+
* schemas, columns and limits. A claim carries one shape or the other, never
|
|
4507
|
+
* both.
|
|
4508
|
+
*/
|
|
4509
|
+
interface ConstraintPolicy {
|
|
4510
|
+
sourceId?: string | null;
|
|
4511
|
+
label?: string;
|
|
4512
|
+
/**
|
|
4513
|
+
* Every table is read from this schema, whatever schema the query wrote —
|
|
4514
|
+
* which is what makes it a restriction: there is no other schema to reach.
|
|
4515
|
+
* Absent means schemas are left exactly as written.
|
|
4516
|
+
*/
|
|
4517
|
+
schema?: string;
|
|
4518
|
+
/** table → readable columns, or `null` for every column. Absent: every table. */
|
|
4519
|
+
readableTables?: Record<string, string[] | null>;
|
|
4520
|
+
/** table → filters, ANDed together. */
|
|
4521
|
+
rowFilters?: Record<string, ConstraintFilter[]>;
|
|
4522
|
+
limits?: {
|
|
4523
|
+
maxRows?: number;
|
|
4524
|
+
maxExecutionSeconds?: number;
|
|
4525
|
+
};
|
|
4526
|
+
/**
|
|
4527
|
+
* Why this policy could not be read. Set rather than dropping the policy:
|
|
4528
|
+
* a dropped policy leaves its source UNRESTRICTED, which is the opposite of
|
|
4529
|
+
* what a malformed restriction should mean. The gate refuses the source.
|
|
4530
|
+
*/
|
|
4531
|
+
invalid?: string;
|
|
4532
|
+
}
|
|
4483
4533
|
interface RequestContext {
|
|
4484
4534
|
principal: Principal;
|
|
4485
4535
|
projectId?: string;
|
|
@@ -4489,6 +4539,11 @@ interface RequestContext {
|
|
|
4489
4539
|
* — see the backend's policy-gate.
|
|
4490
4540
|
*/
|
|
4491
4541
|
policies?: SourcePolicy[];
|
|
4542
|
+
/**
|
|
4543
|
+
* The same restrictions in the constraint shape. Present only when the claim
|
|
4544
|
+
* said `version: 2`, and then `policies` is empty: one claim, one engine.
|
|
4545
|
+
*/
|
|
4546
|
+
constraintPolicies?: ConstraintPolicy[];
|
|
4492
4547
|
/**
|
|
4493
4548
|
* The data sources this user may reach AT ALL, by source id.
|
|
4494
4549
|
*
|
|
@@ -4541,6 +4596,7 @@ declare function runAsUser<T>(user: {
|
|
|
4541
4596
|
projectId?: string;
|
|
4542
4597
|
requestId?: string;
|
|
4543
4598
|
policies?: SourcePolicy[];
|
|
4599
|
+
constraintPolicies?: ConstraintPolicy[];
|
|
4544
4600
|
allowedSources?: string[] | null;
|
|
4545
4601
|
graphVersion?: GraphVersion;
|
|
4546
4602
|
}, fn: () => T): T;
|
|
@@ -4589,6 +4645,35 @@ declare function describeContext(ctx?: RequestContext | undefined): string;
|
|
|
4589
4645
|
/** True when the context represents a signed-in user rather than a trusted job. */
|
|
4590
4646
|
declare function isUserContext(ctx?: RequestContext | undefined): boolean;
|
|
4591
4647
|
|
|
4648
|
+
/**
|
|
4649
|
+
* The constraint policy shape (`version: 2`), read onto the request context.
|
|
4650
|
+
*
|
|
4651
|
+
* Strict, and failing CLOSED, which is the opposite of the legacy parser beside
|
|
4652
|
+
* it. There, dropping something malformed grants LESS. Here it grants MORE: a
|
|
4653
|
+
* dropped policy leaves its source with no restriction at all. So a policy that
|
|
4654
|
+
* cannot be read is kept, marked `invalid`, and the gate refuses the source.
|
|
4655
|
+
*/
|
|
4656
|
+
|
|
4657
|
+
declare function constraintPoliciesFromConfig(raw: unknown): ConstraintPolicy[];
|
|
4658
|
+
|
|
4659
|
+
/**
|
|
4660
|
+
* The original policy shape, read out of the admin-authored per-user config.
|
|
4661
|
+
*
|
|
4662
|
+
* Every step here is defensive and DROPS what it cannot read, because the
|
|
4663
|
+
* config is free-form JSON typed by a human into an admin field. That is a
|
|
4664
|
+
* deliberate trade with a sharp edge — a typo'd policy silently becomes no
|
|
4665
|
+
* policy, i.e. unrestricted. The constraint shape next door takes the opposite
|
|
4666
|
+
* approach for exactly that reason.
|
|
4667
|
+
*/
|
|
4668
|
+
|
|
4669
|
+
/**
|
|
4670
|
+
* Read access policies out of the admin-authored per-user config.
|
|
4671
|
+
*
|
|
4672
|
+
* Accepts either a single object or an array, so one user can be scoped across
|
|
4673
|
+
* several sources — and the object form, whose policies sit under `policies`.
|
|
4674
|
+
*/
|
|
4675
|
+
declare function policiesFromConfig(config: unknown): SourcePolicy[];
|
|
4676
|
+
|
|
4592
4677
|
/**
|
|
4593
4678
|
* Deriving "who is asking" from an incoming WebSocket message.
|
|
4594
4679
|
*
|
|
@@ -4603,6 +4688,8 @@ declare function isUserContext(ctx?: RequestContext | undefined): boolean;
|
|
|
4603
4688
|
/** Everything one request's config says about what the caller may see. */
|
|
4604
4689
|
interface ResolvedAccess {
|
|
4605
4690
|
policies: SourcePolicy[];
|
|
4691
|
+
/** Set instead of `policies` when the claim said `version: 2`. */
|
|
4692
|
+
constraintPolicies: ConstraintPolicy[];
|
|
4606
4693
|
/** `null` means every source; `[]` means none — see `RequestContext.allowedSources`. */
|
|
4607
4694
|
allowedSources: string[] | null;
|
|
4608
4695
|
}
|
|
@@ -4616,19 +4703,6 @@ interface ResolvedAccess {
|
|
|
4616
4703
|
* drop EVERY row filter the customer wrote.
|
|
4617
4704
|
*/
|
|
4618
4705
|
declare function accessFromConfig(config: unknown): ResolvedAccess;
|
|
4619
|
-
/**
|
|
4620
|
-
* Read access policies out of the admin-authored per-user config.
|
|
4621
|
-
*
|
|
4622
|
-
* The config is free-form JSON typed by a human into an admin field, so every
|
|
4623
|
-
* step here is defensive: a malformed entry is DROPPED, never guessed at. That
|
|
4624
|
-
* is a deliberate trade-off with a sharp edge — a typo'd policy silently
|
|
4625
|
-
* becomes no policy, i.e. unrestricted. Validating shapes against the source
|
|
4626
|
-
* schema (and refusing, rather than dropping) is the fix, and is not built yet.
|
|
4627
|
-
*
|
|
4628
|
-
* Accepts either a single object or an array, so one user can be scoped across
|
|
4629
|
-
* several sources — and the object form, whose policies sit under `policies`.
|
|
4630
|
-
*/
|
|
4631
|
-
declare function policiesFromConfig(config: unknown): SourcePolicy[];
|
|
4632
4706
|
/**
|
|
4633
4707
|
* Run `fn` with the caller's identity established.
|
|
4634
4708
|
*
|
|
@@ -5238,7 +5312,8 @@ interface CodingAgentDefinition<TInput = unknown, TOutput = unknown> {
|
|
|
5238
5312
|
promptDir?: string;
|
|
5239
5313
|
/** Override the deployment default for this agent alone. */
|
|
5240
5314
|
harness?: Harness;
|
|
5241
|
-
model
|
|
5315
|
+
/** A function picks the model per run (e.g. by what the question carries); undefined = default. */
|
|
5316
|
+
model?: string | ((input: TInput, ctx: AgentRunContext) => string | undefined);
|
|
5242
5317
|
/**
|
|
5243
5318
|
* Let this agent's shell reach the network. Off by default.
|
|
5244
5319
|
*
|
|
@@ -5454,13 +5529,6 @@ interface RunAgentOptions<TInput> extends AgentRunContext {
|
|
|
5454
5529
|
*/
|
|
5455
5530
|
chat?: boolean;
|
|
5456
5531
|
}
|
|
5457
|
-
/**
|
|
5458
|
-
* Run one agent, end to end.
|
|
5459
|
-
*
|
|
5460
|
-
* Never throws for an agent-side failure — a bad run comes back as a record
|
|
5461
|
-
* with status 'error', because callers are usually crons and message handlers
|
|
5462
|
-
* that must keep going. Genuinely programmer errors (unknown agent id) do throw.
|
|
5463
|
-
*/
|
|
5464
5532
|
declare function runCodingAgent<TInput = unknown, TOutput = unknown>(agentId: string, options?: RunAgentOptions<TInput>): Promise<AgentRunRecord<TOutput>>;
|
|
5465
5533
|
|
|
5466
5534
|
/**
|
|
@@ -6085,4 +6153,4 @@ declare class SuperatomSDK {
|
|
|
6085
6153
|
getConversationSimilarityThreshold(): number;
|
|
6086
6154
|
}
|
|
6087
6155
|
|
|
6088
|
-
export { ALL_COLUMN_KEYS, ANSWER_COMPONENT_NAMES, type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type AnalyticsEventType, type AnalyticsStatus, type AnswerProvider, type AnswerProviderContext, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CATEGORY_KEYS, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type ColInfo, type ColType, type CollectionHandler, type CollectionOperation, type Component, type DBUIBlock, DEFAULT_AGENT_CONFIG, DEFAULT_FMT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type FindingCode, type Fmt, type FmtConfig, type GeneratedFile, type GraphVersion, type Harness, type HybridSearchOptions, INSTRUCTIONS_FILE, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, NUMERIC_KEYS, type NarrationUpdate, type OutputContract, type OutputField, type OutputValidator, type PiSessionListener, type PiSessionState, type PiTranscriptEntry, type PolicyException, type PolicyExceptionTable, type Principal, type PromptAttachment, type PromptContext, type RequestContext, type RerankedResult, type ResolvedAccess, 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 ShimDef, type ShimSummary, type ShimTarget, type SourcePolicy, type SpecToValidate, SuperatomSDK, type SuperatomSDKConfig, type T_RESPONSE, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type ValidationContext, type ValidationFinding, type WorkflowDescriptor, type Workspace, accessFromConfig, analyticsClient, answerCatalogForBinding, answerComponents, anthropicLLM, assertReadOnlySql, bindContext, bridgePreamble, captureContext, clearContextTokens, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, formatFindingsForAgent, geminiLLM, getCodingAgent, getCodingAgentsConfig, getPiSessionState, getRequestContext, groqLLM, hybridRerank, inferColumns, isUserContext, listCodingAgents, llmUsageLogger, logger, makeFmt, mintContextToken, normalizeScriptBody, onAgentRun, onPiSessionUpdate, openaiLLM, policiesFromConfig, projectForDatasetBinding, promptLoader, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, validateComponentSpec, withCapturedContext, writeBridgeShims, writeShims };
|
|
6156
|
+
export { ALL_COLUMN_KEYS, ANSWER_COMPONENT_NAMES, type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type AnalyticsEventType, type AnalyticsStatus, type AnswerProvider, type AnswerProviderContext, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CATEGORY_KEYS, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type ColInfo, type ColType, type CollectionHandler, type CollectionOperation, type Component, type ConstraintFilter, type ConstraintOp, type ConstraintPolicy, type DBUIBlock, DEFAULT_AGENT_CONFIG, DEFAULT_FMT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type FindingCode, type Fmt, type FmtConfig, type GeneratedFile, type GraphVersion, type Harness, type HybridSearchOptions, INSTRUCTIONS_FILE, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, NUMERIC_KEYS, type NarrationUpdate, type OutputContract, type OutputField, type OutputValidator, type PiSessionListener, type PiSessionState, type PiTranscriptEntry, type PolicyException, type PolicyExceptionTable, type Principal, type PromptAttachment, type PromptContext, type RequestContext, type RerankedResult, type ResolvedAccess, 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 ShimDef, type ShimSummary, type ShimTarget, type SourcePolicy, type SpecToValidate, SuperatomSDK, type SuperatomSDKConfig, type T_RESPONSE, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type ValidationContext, type ValidationFinding, type WorkflowDescriptor, type Workspace, accessFromConfig, analyticsClient, answerCatalogForBinding, answerComponents, anthropicLLM, assertReadOnlySql, bindContext, bridgePreamble, captureContext, clearContextTokens, constraintPoliciesFromConfig, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, formatFindingsForAgent, geminiLLM, getCodingAgent, getCodingAgentsConfig, getPiSessionState, getRequestContext, groqLLM, hybridRerank, inferColumns, isUserContext, listCodingAgents, llmUsageLogger, logger, makeFmt, mintContextToken, normalizeScriptBody, onAgentRun, onPiSessionUpdate, openaiLLM, policiesFromConfig, projectForDatasetBinding, promptLoader, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, validateComponentSpec, withCapturedContext, writeBridgeShims, writeShims };
|
package/dist/index.d.ts
CHANGED
|
@@ -4480,6 +4480,56 @@ interface SourcePolicy {
|
|
|
4480
4480
|
/** Grants outside the scope above. Empty or absent means none. */
|
|
4481
4481
|
exceptions?: PolicyException[];
|
|
4482
4482
|
}
|
|
4483
|
+
/**
|
|
4484
|
+
* Operators the constraint engine builds predicates from. A superset of
|
|
4485
|
+
* {@link RowFilter.op}, which the original rewriter is limited to.
|
|
4486
|
+
*/
|
|
4487
|
+
type ConstraintOp = 'in' | 'not_in' | 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'not_like' | 'is_null' | 'is_not_null';
|
|
4488
|
+
/**
|
|
4489
|
+
* One filter in a {@link ConstraintPolicy}.
|
|
4490
|
+
*
|
|
4491
|
+
* No `table`, unlike {@link RowFilter}: these are keyed by table, so a filter
|
|
4492
|
+
* cannot fail to match the table it was written for and leave it unfiltered.
|
|
4493
|
+
*/
|
|
4494
|
+
interface ConstraintFilter {
|
|
4495
|
+
column: string;
|
|
4496
|
+
op?: ConstraintOp;
|
|
4497
|
+
/** Omitted only for `is_null` / `is_not_null`. */
|
|
4498
|
+
values?: unknown[];
|
|
4499
|
+
label?: string;
|
|
4500
|
+
}
|
|
4501
|
+
/**
|
|
4502
|
+
* What one user may see in one source, in the shape the constraint engine reads
|
|
4503
|
+
* (`sqlrewrite/v2/engine.py`).
|
|
4504
|
+
*
|
|
4505
|
+
* Not a superset of {@link SourcePolicy} but a different shape: it adds
|
|
4506
|
+
* schemas, columns and limits. A claim carries one shape or the other, never
|
|
4507
|
+
* both.
|
|
4508
|
+
*/
|
|
4509
|
+
interface ConstraintPolicy {
|
|
4510
|
+
sourceId?: string | null;
|
|
4511
|
+
label?: string;
|
|
4512
|
+
/**
|
|
4513
|
+
* Every table is read from this schema, whatever schema the query wrote —
|
|
4514
|
+
* which is what makes it a restriction: there is no other schema to reach.
|
|
4515
|
+
* Absent means schemas are left exactly as written.
|
|
4516
|
+
*/
|
|
4517
|
+
schema?: string;
|
|
4518
|
+
/** table → readable columns, or `null` for every column. Absent: every table. */
|
|
4519
|
+
readableTables?: Record<string, string[] | null>;
|
|
4520
|
+
/** table → filters, ANDed together. */
|
|
4521
|
+
rowFilters?: Record<string, ConstraintFilter[]>;
|
|
4522
|
+
limits?: {
|
|
4523
|
+
maxRows?: number;
|
|
4524
|
+
maxExecutionSeconds?: number;
|
|
4525
|
+
};
|
|
4526
|
+
/**
|
|
4527
|
+
* Why this policy could not be read. Set rather than dropping the policy:
|
|
4528
|
+
* a dropped policy leaves its source UNRESTRICTED, which is the opposite of
|
|
4529
|
+
* what a malformed restriction should mean. The gate refuses the source.
|
|
4530
|
+
*/
|
|
4531
|
+
invalid?: string;
|
|
4532
|
+
}
|
|
4483
4533
|
interface RequestContext {
|
|
4484
4534
|
principal: Principal;
|
|
4485
4535
|
projectId?: string;
|
|
@@ -4489,6 +4539,11 @@ interface RequestContext {
|
|
|
4489
4539
|
* — see the backend's policy-gate.
|
|
4490
4540
|
*/
|
|
4491
4541
|
policies?: SourcePolicy[];
|
|
4542
|
+
/**
|
|
4543
|
+
* The same restrictions in the constraint shape. Present only when the claim
|
|
4544
|
+
* said `version: 2`, and then `policies` is empty: one claim, one engine.
|
|
4545
|
+
*/
|
|
4546
|
+
constraintPolicies?: ConstraintPolicy[];
|
|
4492
4547
|
/**
|
|
4493
4548
|
* The data sources this user may reach AT ALL, by source id.
|
|
4494
4549
|
*
|
|
@@ -4541,6 +4596,7 @@ declare function runAsUser<T>(user: {
|
|
|
4541
4596
|
projectId?: string;
|
|
4542
4597
|
requestId?: string;
|
|
4543
4598
|
policies?: SourcePolicy[];
|
|
4599
|
+
constraintPolicies?: ConstraintPolicy[];
|
|
4544
4600
|
allowedSources?: string[] | null;
|
|
4545
4601
|
graphVersion?: GraphVersion;
|
|
4546
4602
|
}, fn: () => T): T;
|
|
@@ -4589,6 +4645,35 @@ declare function describeContext(ctx?: RequestContext | undefined): string;
|
|
|
4589
4645
|
/** True when the context represents a signed-in user rather than a trusted job. */
|
|
4590
4646
|
declare function isUserContext(ctx?: RequestContext | undefined): boolean;
|
|
4591
4647
|
|
|
4648
|
+
/**
|
|
4649
|
+
* The constraint policy shape (`version: 2`), read onto the request context.
|
|
4650
|
+
*
|
|
4651
|
+
* Strict, and failing CLOSED, which is the opposite of the legacy parser beside
|
|
4652
|
+
* it. There, dropping something malformed grants LESS. Here it grants MORE: a
|
|
4653
|
+
* dropped policy leaves its source with no restriction at all. So a policy that
|
|
4654
|
+
* cannot be read is kept, marked `invalid`, and the gate refuses the source.
|
|
4655
|
+
*/
|
|
4656
|
+
|
|
4657
|
+
declare function constraintPoliciesFromConfig(raw: unknown): ConstraintPolicy[];
|
|
4658
|
+
|
|
4659
|
+
/**
|
|
4660
|
+
* The original policy shape, read out of the admin-authored per-user config.
|
|
4661
|
+
*
|
|
4662
|
+
* Every step here is defensive and DROPS what it cannot read, because the
|
|
4663
|
+
* config is free-form JSON typed by a human into an admin field. That is a
|
|
4664
|
+
* deliberate trade with a sharp edge — a typo'd policy silently becomes no
|
|
4665
|
+
* policy, i.e. unrestricted. The constraint shape next door takes the opposite
|
|
4666
|
+
* approach for exactly that reason.
|
|
4667
|
+
*/
|
|
4668
|
+
|
|
4669
|
+
/**
|
|
4670
|
+
* Read access policies out of the admin-authored per-user config.
|
|
4671
|
+
*
|
|
4672
|
+
* Accepts either a single object or an array, so one user can be scoped across
|
|
4673
|
+
* several sources — and the object form, whose policies sit under `policies`.
|
|
4674
|
+
*/
|
|
4675
|
+
declare function policiesFromConfig(config: unknown): SourcePolicy[];
|
|
4676
|
+
|
|
4592
4677
|
/**
|
|
4593
4678
|
* Deriving "who is asking" from an incoming WebSocket message.
|
|
4594
4679
|
*
|
|
@@ -4603,6 +4688,8 @@ declare function isUserContext(ctx?: RequestContext | undefined): boolean;
|
|
|
4603
4688
|
/** Everything one request's config says about what the caller may see. */
|
|
4604
4689
|
interface ResolvedAccess {
|
|
4605
4690
|
policies: SourcePolicy[];
|
|
4691
|
+
/** Set instead of `policies` when the claim said `version: 2`. */
|
|
4692
|
+
constraintPolicies: ConstraintPolicy[];
|
|
4606
4693
|
/** `null` means every source; `[]` means none — see `RequestContext.allowedSources`. */
|
|
4607
4694
|
allowedSources: string[] | null;
|
|
4608
4695
|
}
|
|
@@ -4616,19 +4703,6 @@ interface ResolvedAccess {
|
|
|
4616
4703
|
* drop EVERY row filter the customer wrote.
|
|
4617
4704
|
*/
|
|
4618
4705
|
declare function accessFromConfig(config: unknown): ResolvedAccess;
|
|
4619
|
-
/**
|
|
4620
|
-
* Read access policies out of the admin-authored per-user config.
|
|
4621
|
-
*
|
|
4622
|
-
* The config is free-form JSON typed by a human into an admin field, so every
|
|
4623
|
-
* step here is defensive: a malformed entry is DROPPED, never guessed at. That
|
|
4624
|
-
* is a deliberate trade-off with a sharp edge — a typo'd policy silently
|
|
4625
|
-
* becomes no policy, i.e. unrestricted. Validating shapes against the source
|
|
4626
|
-
* schema (and refusing, rather than dropping) is the fix, and is not built yet.
|
|
4627
|
-
*
|
|
4628
|
-
* Accepts either a single object or an array, so one user can be scoped across
|
|
4629
|
-
* several sources — and the object form, whose policies sit under `policies`.
|
|
4630
|
-
*/
|
|
4631
|
-
declare function policiesFromConfig(config: unknown): SourcePolicy[];
|
|
4632
4706
|
/**
|
|
4633
4707
|
* Run `fn` with the caller's identity established.
|
|
4634
4708
|
*
|
|
@@ -5238,7 +5312,8 @@ interface CodingAgentDefinition<TInput = unknown, TOutput = unknown> {
|
|
|
5238
5312
|
promptDir?: string;
|
|
5239
5313
|
/** Override the deployment default for this agent alone. */
|
|
5240
5314
|
harness?: Harness;
|
|
5241
|
-
model
|
|
5315
|
+
/** A function picks the model per run (e.g. by what the question carries); undefined = default. */
|
|
5316
|
+
model?: string | ((input: TInput, ctx: AgentRunContext) => string | undefined);
|
|
5242
5317
|
/**
|
|
5243
5318
|
* Let this agent's shell reach the network. Off by default.
|
|
5244
5319
|
*
|
|
@@ -5454,13 +5529,6 @@ interface RunAgentOptions<TInput> extends AgentRunContext {
|
|
|
5454
5529
|
*/
|
|
5455
5530
|
chat?: boolean;
|
|
5456
5531
|
}
|
|
5457
|
-
/**
|
|
5458
|
-
* Run one agent, end to end.
|
|
5459
|
-
*
|
|
5460
|
-
* Never throws for an agent-side failure — a bad run comes back as a record
|
|
5461
|
-
* with status 'error', because callers are usually crons and message handlers
|
|
5462
|
-
* that must keep going. Genuinely programmer errors (unknown agent id) do throw.
|
|
5463
|
-
*/
|
|
5464
5532
|
declare function runCodingAgent<TInput = unknown, TOutput = unknown>(agentId: string, options?: RunAgentOptions<TInput>): Promise<AgentRunRecord<TOutput>>;
|
|
5465
5533
|
|
|
5466
5534
|
/**
|
|
@@ -6085,4 +6153,4 @@ declare class SuperatomSDK {
|
|
|
6085
6153
|
getConversationSimilarityThreshold(): number;
|
|
6086
6154
|
}
|
|
6087
6155
|
|
|
6088
|
-
export { ALL_COLUMN_KEYS, ANSWER_COMPONENT_NAMES, type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type AnalyticsEventType, type AnalyticsStatus, type AnswerProvider, type AnswerProviderContext, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CATEGORY_KEYS, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type ColInfo, type ColType, type CollectionHandler, type CollectionOperation, type Component, type DBUIBlock, DEFAULT_AGENT_CONFIG, DEFAULT_FMT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type FindingCode, type Fmt, type FmtConfig, type GeneratedFile, type GraphVersion, type Harness, type HybridSearchOptions, INSTRUCTIONS_FILE, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, NUMERIC_KEYS, type NarrationUpdate, type OutputContract, type OutputField, type OutputValidator, type PiSessionListener, type PiSessionState, type PiTranscriptEntry, type PolicyException, type PolicyExceptionTable, type Principal, type PromptAttachment, type PromptContext, type RequestContext, type RerankedResult, type ResolvedAccess, 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 ShimDef, type ShimSummary, type ShimTarget, type SourcePolicy, type SpecToValidate, SuperatomSDK, type SuperatomSDKConfig, type T_RESPONSE, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type ValidationContext, type ValidationFinding, type WorkflowDescriptor, type Workspace, accessFromConfig, analyticsClient, answerCatalogForBinding, answerComponents, anthropicLLM, assertReadOnlySql, bindContext, bridgePreamble, captureContext, clearContextTokens, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, formatFindingsForAgent, geminiLLM, getCodingAgent, getCodingAgentsConfig, getPiSessionState, getRequestContext, groqLLM, hybridRerank, inferColumns, isUserContext, listCodingAgents, llmUsageLogger, logger, makeFmt, mintContextToken, normalizeScriptBody, onAgentRun, onPiSessionUpdate, openaiLLM, policiesFromConfig, projectForDatasetBinding, promptLoader, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, validateComponentSpec, withCapturedContext, writeBridgeShims, writeShims };
|
|
6156
|
+
export { ALL_COLUMN_KEYS, ANSWER_COMPONENT_NAMES, type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type AnalyticsEventType, type AnalyticsStatus, type AnswerProvider, type AnswerProviderContext, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CATEGORY_KEYS, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type ColInfo, type ColType, type CollectionHandler, type CollectionOperation, type Component, type ConstraintFilter, type ConstraintOp, type ConstraintPolicy, type DBUIBlock, DEFAULT_AGENT_CONFIG, DEFAULT_FMT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type FindingCode, type Fmt, type FmtConfig, type GeneratedFile, type GraphVersion, type Harness, type HybridSearchOptions, INSTRUCTIONS_FILE, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, NUMERIC_KEYS, type NarrationUpdate, type OutputContract, type OutputField, type OutputValidator, type PiSessionListener, type PiSessionState, type PiTranscriptEntry, type PolicyException, type PolicyExceptionTable, type Principal, type PromptAttachment, type PromptContext, type RequestContext, type RerankedResult, type ResolvedAccess, 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 ShimDef, type ShimSummary, type ShimTarget, type SourcePolicy, type SpecToValidate, SuperatomSDK, type SuperatomSDKConfig, type T_RESPONSE, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type ValidationContext, type ValidationFinding, type WorkflowDescriptor, type Workspace, accessFromConfig, analyticsClient, answerCatalogForBinding, answerComponents, anthropicLLM, assertReadOnlySql, bindContext, bridgePreamble, captureContext, clearContextTokens, constraintPoliciesFromConfig, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, formatFindingsForAgent, geminiLLM, getCodingAgent, getCodingAgentsConfig, getPiSessionState, getRequestContext, groqLLM, hybridRerank, inferColumns, isUserContext, listCodingAgents, llmUsageLogger, logger, makeFmt, mintContextToken, normalizeScriptBody, onAgentRun, onPiSessionUpdate, openaiLLM, policiesFromConfig, projectForDatasetBinding, promptLoader, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, validateComponentSpec, withCapturedContext, writeBridgeShims, writeShims };
|
package/dist/index.js
CHANGED
|
@@ -62,6 +62,7 @@ __export(index_exports, {
|
|
|
62
62
|
bridgePreamble: () => bridgePreamble,
|
|
63
63
|
captureContext: () => captureContext,
|
|
64
64
|
clearContextTokens: () => clearContextTokens,
|
|
65
|
+
constraintPoliciesFromConfig: () => constraintPoliciesFromConfig,
|
|
65
66
|
contextTokenCount: () => contextTokenCount,
|
|
66
67
|
createCodexSession: () => createCodexSession,
|
|
67
68
|
createCodingAgentSession: () => createCodingAgentSession,
|
|
@@ -1952,7 +1953,17 @@ function runWithContext(ctx, fn) {
|
|
|
1952
1953
|
return getStorage().run(ctx, fn);
|
|
1953
1954
|
}
|
|
1954
1955
|
function runAsUser(user, fn) {
|
|
1955
|
-
const {
|
|
1956
|
+
const {
|
|
1957
|
+
userId,
|
|
1958
|
+
orgId,
|
|
1959
|
+
role,
|
|
1960
|
+
projectId,
|
|
1961
|
+
requestId,
|
|
1962
|
+
policies,
|
|
1963
|
+
constraintPolicies,
|
|
1964
|
+
allowedSources,
|
|
1965
|
+
graphVersion
|
|
1966
|
+
} = user;
|
|
1956
1967
|
return runWithContext(
|
|
1957
1968
|
// `allowedSources` is spread in only when given, so an absent restriction
|
|
1958
1969
|
// stays absent rather than becoming an explicit `undefined` that a later
|
|
@@ -1962,6 +1973,7 @@ function runAsUser(user, fn) {
|
|
|
1962
1973
|
projectId,
|
|
1963
1974
|
requestId,
|
|
1964
1975
|
policies,
|
|
1976
|
+
...constraintPolicies?.length ? { constraintPolicies } : {},
|
|
1965
1977
|
...allowedSources !== void 0 ? { allowedSources } : {},
|
|
1966
1978
|
...graphVersion !== void 0 ? { graphVersion } : {}
|
|
1967
1979
|
},
|
|
@@ -2642,42 +2654,148 @@ function buildDirectToolCacheKey(toolId, parameters) {
|
|
|
2642
2654
|
return `et-direct:${toolId}:${stableStringify(parameters || {})}`;
|
|
2643
2655
|
}
|
|
2644
2656
|
|
|
2645
|
-
// src/handlers/
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2657
|
+
// src/handlers/data-access/v2/policies.ts
|
|
2658
|
+
var CONSTRAINT_OPS = [
|
|
2659
|
+
"in",
|
|
2660
|
+
"not_in",
|
|
2661
|
+
"eq",
|
|
2662
|
+
"ne",
|
|
2663
|
+
"gt",
|
|
2664
|
+
"gte",
|
|
2665
|
+
"lt",
|
|
2666
|
+
"lte",
|
|
2667
|
+
"like",
|
|
2668
|
+
"not_like",
|
|
2669
|
+
"is_null",
|
|
2670
|
+
"is_not_null"
|
|
2671
|
+
];
|
|
2672
|
+
var NO_VALUE_OPS = /* @__PURE__ */ new Set(["is_null", "is_not_null"]);
|
|
2673
|
+
function constraintPoliciesFromConfig(raw) {
|
|
2674
|
+
const entries = Array.isArray(raw) ? raw : [raw];
|
|
2675
|
+
const out = [];
|
|
2676
|
+
for (const entry of entries) {
|
|
2677
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
2678
|
+
const e = entry;
|
|
2679
|
+
const sourceId = typeof e.sourceId === "string" && e.sourceId ? e.sourceId : null;
|
|
2680
|
+
const label = typeof e.label === "string" && e.label.trim() ? e.label.trim() : void 0;
|
|
2681
|
+
const bad = (why) => ({ sourceId, label, invalid: why });
|
|
2682
|
+
let schema2;
|
|
2683
|
+
if (e.schema !== void 0 && e.schema !== null) {
|
|
2684
|
+
if (typeof e.schema !== "string" || !e.schema.trim()) {
|
|
2685
|
+
out.push(bad("schema must be a schema name"));
|
|
2686
|
+
continue;
|
|
2687
|
+
}
|
|
2688
|
+
schema2 = e.schema.trim();
|
|
2689
|
+
}
|
|
2690
|
+
let readableTables;
|
|
2691
|
+
let tablesBad;
|
|
2692
|
+
if (e.readableTables !== void 0 && e.readableTables !== null) {
|
|
2693
|
+
if (typeof e.readableTables !== "object" || Array.isArray(e.readableTables)) {
|
|
2694
|
+
out.push(bad("readableTables must be an object of table to columns"));
|
|
2695
|
+
continue;
|
|
2696
|
+
}
|
|
2697
|
+
readableTables = {};
|
|
2698
|
+
for (const [table, cols] of Object.entries(e.readableTables)) {
|
|
2699
|
+
if (cols === null) {
|
|
2700
|
+
readableTables[table] = null;
|
|
2701
|
+
continue;
|
|
2702
|
+
}
|
|
2703
|
+
if (!Array.isArray(cols) || cols.length === 0) {
|
|
2704
|
+
tablesBad = `readableTables["${table}"] must be a non-empty list or null`;
|
|
2705
|
+
break;
|
|
2706
|
+
}
|
|
2707
|
+
const columns = cols.filter((c) => typeof c === "string" && !!c.trim()).map((c) => c.trim());
|
|
2708
|
+
if (columns.length !== cols.length) {
|
|
2709
|
+
tablesBad = `readableTables["${table}"] has an entry that is not a column name`;
|
|
2710
|
+
break;
|
|
2711
|
+
}
|
|
2712
|
+
readableTables[table] = columns;
|
|
2713
|
+
}
|
|
2714
|
+
if (!tablesBad && Object.keys(readableTables).length === 0) {
|
|
2715
|
+
tablesBad = "readableTables names no tables \u2014 omit it to allow every table";
|
|
2716
|
+
}
|
|
2717
|
+
if (tablesBad) {
|
|
2718
|
+
out.push(bad(tablesBad));
|
|
2719
|
+
continue;
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
const rowFilters = {};
|
|
2723
|
+
let filtersBad;
|
|
2724
|
+
const rawFilters = e.rowFilters;
|
|
2725
|
+
if (rawFilters !== void 0 && rawFilters !== null) {
|
|
2726
|
+
if (typeof rawFilters !== "object" || Array.isArray(rawFilters)) {
|
|
2727
|
+
filtersBad = "rowFilters must be an object keyed by table";
|
|
2728
|
+
} else {
|
|
2729
|
+
for (const [table, items] of Object.entries(rawFilters)) {
|
|
2730
|
+
if (readableTables && !(table in readableTables)) {
|
|
2731
|
+
filtersBad = `rowFilters names "${table}", which readableTables does not allow`;
|
|
2732
|
+
break;
|
|
2733
|
+
}
|
|
2734
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
2735
|
+
filtersBad = `rowFilters["${table}"] must be a non-empty list`;
|
|
2736
|
+
break;
|
|
2737
|
+
}
|
|
2738
|
+
const parsed = [];
|
|
2739
|
+
for (const item of items) {
|
|
2740
|
+
if (!item || typeof item !== "object") {
|
|
2741
|
+
filtersBad = `rowFilters["${table}"] has an entry that is not an object`;
|
|
2742
|
+
break;
|
|
2743
|
+
}
|
|
2744
|
+
const f = item;
|
|
2745
|
+
if (typeof f.column !== "string" || !f.column.trim()) {
|
|
2746
|
+
filtersBad = `a filter on "${table}" has no column`;
|
|
2747
|
+
break;
|
|
2748
|
+
}
|
|
2749
|
+
const op = typeof f.op === "string" ? f.op.toLowerCase() : "in";
|
|
2750
|
+
if (!CONSTRAINT_OPS.includes(op)) {
|
|
2751
|
+
filtersBad = `unsupported operator "${f.op}" on "${table}.${f.column}"`;
|
|
2752
|
+
break;
|
|
2753
|
+
}
|
|
2754
|
+
const values = Array.isArray(f.values) ? f.values : [];
|
|
2755
|
+
if (!NO_VALUE_OPS.has(op) && values.length === 0) {
|
|
2756
|
+
filtersBad = `the filter on "${table}.${f.column}" has no values`;
|
|
2757
|
+
break;
|
|
2758
|
+
}
|
|
2759
|
+
parsed.push({
|
|
2760
|
+
column: f.column.trim(),
|
|
2761
|
+
op,
|
|
2762
|
+
...NO_VALUE_OPS.has(op) ? {} : { values },
|
|
2763
|
+
label: typeof f.label === "string" && f.label.trim() ? f.label.trim() : void 0
|
|
2764
|
+
});
|
|
2765
|
+
}
|
|
2766
|
+
if (filtersBad) break;
|
|
2767
|
+
rowFilters[table] = parsed;
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
if (filtersBad) {
|
|
2772
|
+
out.push(bad(filtersBad));
|
|
2773
|
+
continue;
|
|
2774
|
+
}
|
|
2775
|
+
const rawLimits = e.limits;
|
|
2776
|
+
const num = (v) => typeof v === "number" && Number.isInteger(v) && v > 0 ? v : void 0;
|
|
2777
|
+
const limits = rawLimits ? { maxRows: num(rawLimits.maxRows), maxExecutionSeconds: num(rawLimits.maxExecutionSeconds) } : void 0;
|
|
2778
|
+
out.push({
|
|
2779
|
+
sourceId,
|
|
2780
|
+
label,
|
|
2781
|
+
...schema2 ? { schema: schema2 } : {},
|
|
2782
|
+
...readableTables ? { readableTables } : {},
|
|
2783
|
+
...Object.keys(rowFilters).length ? { rowFilters } : {},
|
|
2784
|
+
...limits ? { limits } : {}
|
|
2785
|
+
});
|
|
2786
|
+
}
|
|
2787
|
+
return out;
|
|
2649
2788
|
}
|
|
2789
|
+
|
|
2790
|
+
// src/handlers/data-access/shape.ts
|
|
2650
2791
|
function scopedForm(config2) {
|
|
2651
2792
|
if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) return void 0;
|
|
2652
2793
|
const c = config2;
|
|
2653
2794
|
return "allowedSources" in c || "policies" in c ? c : void 0;
|
|
2654
2795
|
}
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
if (!warnedBadSources) {
|
|
2659
|
-
warnedBadSources = true;
|
|
2660
|
-
logger.warn(
|
|
2661
|
-
`[RequestIdentity] "allowedSources" is ${typeof value}, not a list of source ids \u2014 treating it as NO sources rather than all of them. Fix the config: "allowedSources": ["mssql-1a2b"].`
|
|
2662
|
-
);
|
|
2663
|
-
}
|
|
2664
|
-
return [];
|
|
2665
|
-
}
|
|
2666
|
-
const out = [];
|
|
2667
|
-
for (const item of value) {
|
|
2668
|
-
if (typeof item !== "string" || !item.trim()) continue;
|
|
2669
|
-
const id = item.trim();
|
|
2670
|
-
if (!out.includes(id)) out.push(id);
|
|
2671
|
-
}
|
|
2672
|
-
return out;
|
|
2673
|
-
}
|
|
2674
|
-
function accessFromConfig(config2) {
|
|
2675
|
-
const scoped = scopedForm(config2);
|
|
2676
|
-
return {
|
|
2677
|
-
policies: policiesFromConfig(config2),
|
|
2678
|
-
allowedSources: scoped ? allowedSourcesFrom(scoped.allowedSources) : null
|
|
2679
|
-
};
|
|
2680
|
-
}
|
|
2796
|
+
|
|
2797
|
+
// src/handlers/data-access/v1/policies.ts
|
|
2798
|
+
var warnedUnlabelled = false;
|
|
2681
2799
|
function exceptionsFromConfig(raw) {
|
|
2682
2800
|
if (!Array.isArray(raw)) return [];
|
|
2683
2801
|
const str = (v) => typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
@@ -2756,16 +2874,55 @@ function policiesFromConfig(config2) {
|
|
|
2756
2874
|
}
|
|
2757
2875
|
return out;
|
|
2758
2876
|
}
|
|
2877
|
+
|
|
2878
|
+
// src/handlers/request-identity.ts
|
|
2879
|
+
function graphVersionOf(v) {
|
|
2880
|
+
if (v === "draft") return "draft";
|
|
2881
|
+
return Number.isInteger(v) && v > 0 ? v : void 0;
|
|
2882
|
+
}
|
|
2883
|
+
function allowedSourcesFrom(value) {
|
|
2884
|
+
if (value === void 0 || value === null) return null;
|
|
2885
|
+
if (!Array.isArray(value)) {
|
|
2886
|
+
if (!warnedBadSources) {
|
|
2887
|
+
warnedBadSources = true;
|
|
2888
|
+
logger.warn(
|
|
2889
|
+
`[RequestIdentity] "allowedSources" is ${typeof value}, not a list of source ids \u2014 treating it as NO sources rather than all of them. Fix the config: "allowedSources": ["mssql-1a2b"].`
|
|
2890
|
+
);
|
|
2891
|
+
}
|
|
2892
|
+
return [];
|
|
2893
|
+
}
|
|
2894
|
+
const out = [];
|
|
2895
|
+
for (const item of value) {
|
|
2896
|
+
if (typeof item !== "string" || !item.trim()) continue;
|
|
2897
|
+
const id = item.trim();
|
|
2898
|
+
if (!out.includes(id)) out.push(id);
|
|
2899
|
+
}
|
|
2900
|
+
return out;
|
|
2901
|
+
}
|
|
2902
|
+
function accessFromConfig(config2) {
|
|
2903
|
+
const scoped = scopedForm(config2);
|
|
2904
|
+
const allowedSources = scoped ? allowedSourcesFrom(scoped.allowedSources) : null;
|
|
2905
|
+
if (scoped?.version === 2) {
|
|
2906
|
+
return {
|
|
2907
|
+
policies: [],
|
|
2908
|
+
constraintPolicies: constraintPoliciesFromConfig(scoped.policies),
|
|
2909
|
+
allowedSources
|
|
2910
|
+
};
|
|
2911
|
+
}
|
|
2912
|
+
return { policies: policiesFromConfig(config2), constraintPolicies: [], allowedSources };
|
|
2913
|
+
}
|
|
2759
2914
|
var warnedUntrusted = false;
|
|
2760
2915
|
var warnedAnonymous = false;
|
|
2761
|
-
var warnedUnlabelled = false;
|
|
2762
2916
|
var warnedBadSources = false;
|
|
2763
2917
|
var announcedVerified = false;
|
|
2764
2918
|
var reportedIdMismatches = /* @__PURE__ */ new Set();
|
|
2765
2919
|
function runWithMessageIdentity(message, fn) {
|
|
2766
2920
|
const verified = message?.authContext;
|
|
2767
2921
|
const requestId = message?.id;
|
|
2768
|
-
const { policies, allowedSources } = verified ? accessFromConfig(verified.config) : accessFromConfig(message?.payload?.config);
|
|
2922
|
+
const { policies, constraintPolicies, allowedSources } = verified ? accessFromConfig(verified.config) : accessFromConfig(message?.payload?.config);
|
|
2923
|
+
logger.info(
|
|
2924
|
+
`[RequestIdentity] ${message?.type ?? "?"}: access from ${verified ? "authContext" : "payload"}${verified && verified.config == null ? " (none on it)" : ""}, allowedSources=${allowedSources === null ? "every source" : `[${allowedSources.join(", ") || "NONE"}]`}, ${constraintPolicies.length} constraint policy(ies), ${policies.length} row policy(ies)`
|
|
2925
|
+
);
|
|
2769
2926
|
if (verified?.userId) {
|
|
2770
2927
|
const claimedId = message?.payload?.userId;
|
|
2771
2928
|
if (!announcedVerified) {
|
|
@@ -2790,6 +2947,7 @@ function runWithMessageIdentity(message, fn) {
|
|
|
2790
2947
|
role: verified.role,
|
|
2791
2948
|
requestId,
|
|
2792
2949
|
policies,
|
|
2950
|
+
constraintPolicies,
|
|
2793
2951
|
// `?? undefined` so "no restriction" leaves the key off the context
|
|
2794
2952
|
// entirely; `[]` is passed through as the deny-everything it means.
|
|
2795
2953
|
allowedSources: allowedSources ?? void 0,
|
|
@@ -2807,7 +2965,10 @@ function runWithMessageIdentity(message, fn) {
|
|
|
2807
2965
|
"[RequestIdentity] Using the client-supplied payload.userId as the principal \u2014 the relay is not stamping a verified authContext yet, so this identity is NOT trustworthy. Fine for plumbing; do not enable policy enforcement until the relay change lands."
|
|
2808
2966
|
);
|
|
2809
2967
|
}
|
|
2810
|
-
return runAsUser(
|
|
2968
|
+
return runAsUser(
|
|
2969
|
+
{ userId: claimed, requestId, policies, constraintPolicies, allowedSources: allowedSources ?? void 0 },
|
|
2970
|
+
fn
|
|
2971
|
+
);
|
|
2811
2972
|
}
|
|
2812
2973
|
if (!warnedAnonymous) {
|
|
2813
2974
|
warnedAnonymous = true;
|
|
@@ -25422,6 +25583,9 @@ async function pruneRuns(agentDir, keep) {
|
|
|
25422
25583
|
} catch {
|
|
25423
25584
|
}
|
|
25424
25585
|
}
|
|
25586
|
+
function runModel(def, input, ctx, fallback) {
|
|
25587
|
+
return (typeof def.model === "function" ? def.model(input, ctx) : def.model) || fallback;
|
|
25588
|
+
}
|
|
25425
25589
|
async function runCodingAgent(agentId, options = {}) {
|
|
25426
25590
|
const def = getCodingAgent(agentId);
|
|
25427
25591
|
if (!def) {
|
|
@@ -25513,9 +25677,10 @@ async function runCodingAgent(agentId, options = {}) {
|
|
|
25513
25677
|
(runAsJob && def.buildPrompt ? await def.buildPrompt(ws, input, ctx) : outputPath ? `Carry out the task described in ${INSTRUCTIONS_FILE}. Write your finished result to this exact absolute path: ${outputPath}` : `Carry out the task described in ${INSTRUCTIONS_FILE}.`);
|
|
25514
25678
|
const tools = { ...cfg.sharedTools ?? {}, ...def.tools ?? {} };
|
|
25515
25679
|
const sessionEnv = def.env ? await def.env(input, ctx) : void 0;
|
|
25680
|
+
const model = runModel(def, input, ctx, cfg.model);
|
|
25516
25681
|
const session = createCodingAgentSession(def.harness || cfg.harness, {
|
|
25517
25682
|
cwd: dir,
|
|
25518
|
-
model
|
|
25683
|
+
model,
|
|
25519
25684
|
resumeId,
|
|
25520
25685
|
instructionsFile: INSTRUCTIONS_FILE,
|
|
25521
25686
|
// undefined, not {}, when this agent has no tools — see the driver.
|
|
@@ -25602,7 +25767,7 @@ async function runCodingAgent(agentId, options = {}) {
|
|
|
25602
25767
|
logger.warn(`[CodingAgent:${def.id}] deliverable rejected (${message}) \u2014 asking the agent to repair it`);
|
|
25603
25768
|
const repair = createCodingAgentSession(def.harness || cfg.harness, {
|
|
25604
25769
|
cwd: dir,
|
|
25605
|
-
model
|
|
25770
|
+
model,
|
|
25606
25771
|
resumeId: result.sessionId,
|
|
25607
25772
|
instructionsFile: INSTRUCTIONS_FILE,
|
|
25608
25773
|
mcpServers: tools && Object.keys(tools).length ? tools : void 0,
|
|
@@ -30205,6 +30370,7 @@ var SuperatomSDK = class {
|
|
|
30205
30370
|
bridgePreamble,
|
|
30206
30371
|
captureContext,
|
|
30207
30372
|
clearContextTokens,
|
|
30373
|
+
constraintPoliciesFromConfig,
|
|
30208
30374
|
contextTokenCount,
|
|
30209
30375
|
createCodexSession,
|
|
30210
30376
|
createCodingAgentSession,
|
package/dist/index.mjs
CHANGED
|
@@ -1840,7 +1840,17 @@ function runWithContext(ctx, fn) {
|
|
|
1840
1840
|
return getStorage().run(ctx, fn);
|
|
1841
1841
|
}
|
|
1842
1842
|
function runAsUser(user, fn) {
|
|
1843
|
-
const {
|
|
1843
|
+
const {
|
|
1844
|
+
userId,
|
|
1845
|
+
orgId,
|
|
1846
|
+
role,
|
|
1847
|
+
projectId,
|
|
1848
|
+
requestId,
|
|
1849
|
+
policies,
|
|
1850
|
+
constraintPolicies,
|
|
1851
|
+
allowedSources,
|
|
1852
|
+
graphVersion
|
|
1853
|
+
} = user;
|
|
1844
1854
|
return runWithContext(
|
|
1845
1855
|
// `allowedSources` is spread in only when given, so an absent restriction
|
|
1846
1856
|
// stays absent rather than becoming an explicit `undefined` that a later
|
|
@@ -1850,6 +1860,7 @@ function runAsUser(user, fn) {
|
|
|
1850
1860
|
projectId,
|
|
1851
1861
|
requestId,
|
|
1852
1862
|
policies,
|
|
1863
|
+
...constraintPolicies?.length ? { constraintPolicies } : {},
|
|
1853
1864
|
...allowedSources !== void 0 ? { allowedSources } : {},
|
|
1854
1865
|
...graphVersion !== void 0 ? { graphVersion } : {}
|
|
1855
1866
|
},
|
|
@@ -2530,42 +2541,148 @@ function buildDirectToolCacheKey(toolId, parameters) {
|
|
|
2530
2541
|
return `et-direct:${toolId}:${stableStringify(parameters || {})}`;
|
|
2531
2542
|
}
|
|
2532
2543
|
|
|
2533
|
-
// src/handlers/
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2544
|
+
// src/handlers/data-access/v2/policies.ts
|
|
2545
|
+
var CONSTRAINT_OPS = [
|
|
2546
|
+
"in",
|
|
2547
|
+
"not_in",
|
|
2548
|
+
"eq",
|
|
2549
|
+
"ne",
|
|
2550
|
+
"gt",
|
|
2551
|
+
"gte",
|
|
2552
|
+
"lt",
|
|
2553
|
+
"lte",
|
|
2554
|
+
"like",
|
|
2555
|
+
"not_like",
|
|
2556
|
+
"is_null",
|
|
2557
|
+
"is_not_null"
|
|
2558
|
+
];
|
|
2559
|
+
var NO_VALUE_OPS = /* @__PURE__ */ new Set(["is_null", "is_not_null"]);
|
|
2560
|
+
function constraintPoliciesFromConfig(raw) {
|
|
2561
|
+
const entries = Array.isArray(raw) ? raw : [raw];
|
|
2562
|
+
const out = [];
|
|
2563
|
+
for (const entry of entries) {
|
|
2564
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
2565
|
+
const e = entry;
|
|
2566
|
+
const sourceId = typeof e.sourceId === "string" && e.sourceId ? e.sourceId : null;
|
|
2567
|
+
const label = typeof e.label === "string" && e.label.trim() ? e.label.trim() : void 0;
|
|
2568
|
+
const bad = (why) => ({ sourceId, label, invalid: why });
|
|
2569
|
+
let schema2;
|
|
2570
|
+
if (e.schema !== void 0 && e.schema !== null) {
|
|
2571
|
+
if (typeof e.schema !== "string" || !e.schema.trim()) {
|
|
2572
|
+
out.push(bad("schema must be a schema name"));
|
|
2573
|
+
continue;
|
|
2574
|
+
}
|
|
2575
|
+
schema2 = e.schema.trim();
|
|
2576
|
+
}
|
|
2577
|
+
let readableTables;
|
|
2578
|
+
let tablesBad;
|
|
2579
|
+
if (e.readableTables !== void 0 && e.readableTables !== null) {
|
|
2580
|
+
if (typeof e.readableTables !== "object" || Array.isArray(e.readableTables)) {
|
|
2581
|
+
out.push(bad("readableTables must be an object of table to columns"));
|
|
2582
|
+
continue;
|
|
2583
|
+
}
|
|
2584
|
+
readableTables = {};
|
|
2585
|
+
for (const [table, cols] of Object.entries(e.readableTables)) {
|
|
2586
|
+
if (cols === null) {
|
|
2587
|
+
readableTables[table] = null;
|
|
2588
|
+
continue;
|
|
2589
|
+
}
|
|
2590
|
+
if (!Array.isArray(cols) || cols.length === 0) {
|
|
2591
|
+
tablesBad = `readableTables["${table}"] must be a non-empty list or null`;
|
|
2592
|
+
break;
|
|
2593
|
+
}
|
|
2594
|
+
const columns = cols.filter((c) => typeof c === "string" && !!c.trim()).map((c) => c.trim());
|
|
2595
|
+
if (columns.length !== cols.length) {
|
|
2596
|
+
tablesBad = `readableTables["${table}"] has an entry that is not a column name`;
|
|
2597
|
+
break;
|
|
2598
|
+
}
|
|
2599
|
+
readableTables[table] = columns;
|
|
2600
|
+
}
|
|
2601
|
+
if (!tablesBad && Object.keys(readableTables).length === 0) {
|
|
2602
|
+
tablesBad = "readableTables names no tables \u2014 omit it to allow every table";
|
|
2603
|
+
}
|
|
2604
|
+
if (tablesBad) {
|
|
2605
|
+
out.push(bad(tablesBad));
|
|
2606
|
+
continue;
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
const rowFilters = {};
|
|
2610
|
+
let filtersBad;
|
|
2611
|
+
const rawFilters = e.rowFilters;
|
|
2612
|
+
if (rawFilters !== void 0 && rawFilters !== null) {
|
|
2613
|
+
if (typeof rawFilters !== "object" || Array.isArray(rawFilters)) {
|
|
2614
|
+
filtersBad = "rowFilters must be an object keyed by table";
|
|
2615
|
+
} else {
|
|
2616
|
+
for (const [table, items] of Object.entries(rawFilters)) {
|
|
2617
|
+
if (readableTables && !(table in readableTables)) {
|
|
2618
|
+
filtersBad = `rowFilters names "${table}", which readableTables does not allow`;
|
|
2619
|
+
break;
|
|
2620
|
+
}
|
|
2621
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
2622
|
+
filtersBad = `rowFilters["${table}"] must be a non-empty list`;
|
|
2623
|
+
break;
|
|
2624
|
+
}
|
|
2625
|
+
const parsed = [];
|
|
2626
|
+
for (const item of items) {
|
|
2627
|
+
if (!item || typeof item !== "object") {
|
|
2628
|
+
filtersBad = `rowFilters["${table}"] has an entry that is not an object`;
|
|
2629
|
+
break;
|
|
2630
|
+
}
|
|
2631
|
+
const f = item;
|
|
2632
|
+
if (typeof f.column !== "string" || !f.column.trim()) {
|
|
2633
|
+
filtersBad = `a filter on "${table}" has no column`;
|
|
2634
|
+
break;
|
|
2635
|
+
}
|
|
2636
|
+
const op = typeof f.op === "string" ? f.op.toLowerCase() : "in";
|
|
2637
|
+
if (!CONSTRAINT_OPS.includes(op)) {
|
|
2638
|
+
filtersBad = `unsupported operator "${f.op}" on "${table}.${f.column}"`;
|
|
2639
|
+
break;
|
|
2640
|
+
}
|
|
2641
|
+
const values = Array.isArray(f.values) ? f.values : [];
|
|
2642
|
+
if (!NO_VALUE_OPS.has(op) && values.length === 0) {
|
|
2643
|
+
filtersBad = `the filter on "${table}.${f.column}" has no values`;
|
|
2644
|
+
break;
|
|
2645
|
+
}
|
|
2646
|
+
parsed.push({
|
|
2647
|
+
column: f.column.trim(),
|
|
2648
|
+
op,
|
|
2649
|
+
...NO_VALUE_OPS.has(op) ? {} : { values },
|
|
2650
|
+
label: typeof f.label === "string" && f.label.trim() ? f.label.trim() : void 0
|
|
2651
|
+
});
|
|
2652
|
+
}
|
|
2653
|
+
if (filtersBad) break;
|
|
2654
|
+
rowFilters[table] = parsed;
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
if (filtersBad) {
|
|
2659
|
+
out.push(bad(filtersBad));
|
|
2660
|
+
continue;
|
|
2661
|
+
}
|
|
2662
|
+
const rawLimits = e.limits;
|
|
2663
|
+
const num = (v) => typeof v === "number" && Number.isInteger(v) && v > 0 ? v : void 0;
|
|
2664
|
+
const limits = rawLimits ? { maxRows: num(rawLimits.maxRows), maxExecutionSeconds: num(rawLimits.maxExecutionSeconds) } : void 0;
|
|
2665
|
+
out.push({
|
|
2666
|
+
sourceId,
|
|
2667
|
+
label,
|
|
2668
|
+
...schema2 ? { schema: schema2 } : {},
|
|
2669
|
+
...readableTables ? { readableTables } : {},
|
|
2670
|
+
...Object.keys(rowFilters).length ? { rowFilters } : {},
|
|
2671
|
+
...limits ? { limits } : {}
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2674
|
+
return out;
|
|
2537
2675
|
}
|
|
2676
|
+
|
|
2677
|
+
// src/handlers/data-access/shape.ts
|
|
2538
2678
|
function scopedForm(config2) {
|
|
2539
2679
|
if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) return void 0;
|
|
2540
2680
|
const c = config2;
|
|
2541
2681
|
return "allowedSources" in c || "policies" in c ? c : void 0;
|
|
2542
2682
|
}
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
if (!warnedBadSources) {
|
|
2547
|
-
warnedBadSources = true;
|
|
2548
|
-
logger.warn(
|
|
2549
|
-
`[RequestIdentity] "allowedSources" is ${typeof value}, not a list of source ids \u2014 treating it as NO sources rather than all of them. Fix the config: "allowedSources": ["mssql-1a2b"].`
|
|
2550
|
-
);
|
|
2551
|
-
}
|
|
2552
|
-
return [];
|
|
2553
|
-
}
|
|
2554
|
-
const out = [];
|
|
2555
|
-
for (const item of value) {
|
|
2556
|
-
if (typeof item !== "string" || !item.trim()) continue;
|
|
2557
|
-
const id = item.trim();
|
|
2558
|
-
if (!out.includes(id)) out.push(id);
|
|
2559
|
-
}
|
|
2560
|
-
return out;
|
|
2561
|
-
}
|
|
2562
|
-
function accessFromConfig(config2) {
|
|
2563
|
-
const scoped = scopedForm(config2);
|
|
2564
|
-
return {
|
|
2565
|
-
policies: policiesFromConfig(config2),
|
|
2566
|
-
allowedSources: scoped ? allowedSourcesFrom(scoped.allowedSources) : null
|
|
2567
|
-
};
|
|
2568
|
-
}
|
|
2683
|
+
|
|
2684
|
+
// src/handlers/data-access/v1/policies.ts
|
|
2685
|
+
var warnedUnlabelled = false;
|
|
2569
2686
|
function exceptionsFromConfig(raw) {
|
|
2570
2687
|
if (!Array.isArray(raw)) return [];
|
|
2571
2688
|
const str = (v) => typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
@@ -2644,16 +2761,55 @@ function policiesFromConfig(config2) {
|
|
|
2644
2761
|
}
|
|
2645
2762
|
return out;
|
|
2646
2763
|
}
|
|
2764
|
+
|
|
2765
|
+
// src/handlers/request-identity.ts
|
|
2766
|
+
function graphVersionOf(v) {
|
|
2767
|
+
if (v === "draft") return "draft";
|
|
2768
|
+
return Number.isInteger(v) && v > 0 ? v : void 0;
|
|
2769
|
+
}
|
|
2770
|
+
function allowedSourcesFrom(value) {
|
|
2771
|
+
if (value === void 0 || value === null) return null;
|
|
2772
|
+
if (!Array.isArray(value)) {
|
|
2773
|
+
if (!warnedBadSources) {
|
|
2774
|
+
warnedBadSources = true;
|
|
2775
|
+
logger.warn(
|
|
2776
|
+
`[RequestIdentity] "allowedSources" is ${typeof value}, not a list of source ids \u2014 treating it as NO sources rather than all of them. Fix the config: "allowedSources": ["mssql-1a2b"].`
|
|
2777
|
+
);
|
|
2778
|
+
}
|
|
2779
|
+
return [];
|
|
2780
|
+
}
|
|
2781
|
+
const out = [];
|
|
2782
|
+
for (const item of value) {
|
|
2783
|
+
if (typeof item !== "string" || !item.trim()) continue;
|
|
2784
|
+
const id = item.trim();
|
|
2785
|
+
if (!out.includes(id)) out.push(id);
|
|
2786
|
+
}
|
|
2787
|
+
return out;
|
|
2788
|
+
}
|
|
2789
|
+
function accessFromConfig(config2) {
|
|
2790
|
+
const scoped = scopedForm(config2);
|
|
2791
|
+
const allowedSources = scoped ? allowedSourcesFrom(scoped.allowedSources) : null;
|
|
2792
|
+
if (scoped?.version === 2) {
|
|
2793
|
+
return {
|
|
2794
|
+
policies: [],
|
|
2795
|
+
constraintPolicies: constraintPoliciesFromConfig(scoped.policies),
|
|
2796
|
+
allowedSources
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
return { policies: policiesFromConfig(config2), constraintPolicies: [], allowedSources };
|
|
2800
|
+
}
|
|
2647
2801
|
var warnedUntrusted = false;
|
|
2648
2802
|
var warnedAnonymous = false;
|
|
2649
|
-
var warnedUnlabelled = false;
|
|
2650
2803
|
var warnedBadSources = false;
|
|
2651
2804
|
var announcedVerified = false;
|
|
2652
2805
|
var reportedIdMismatches = /* @__PURE__ */ new Set();
|
|
2653
2806
|
function runWithMessageIdentity(message, fn) {
|
|
2654
2807
|
const verified = message?.authContext;
|
|
2655
2808
|
const requestId = message?.id;
|
|
2656
|
-
const { policies, allowedSources } = verified ? accessFromConfig(verified.config) : accessFromConfig(message?.payload?.config);
|
|
2809
|
+
const { policies, constraintPolicies, allowedSources } = verified ? accessFromConfig(verified.config) : accessFromConfig(message?.payload?.config);
|
|
2810
|
+
logger.info(
|
|
2811
|
+
`[RequestIdentity] ${message?.type ?? "?"}: access from ${verified ? "authContext" : "payload"}${verified && verified.config == null ? " (none on it)" : ""}, allowedSources=${allowedSources === null ? "every source" : `[${allowedSources.join(", ") || "NONE"}]`}, ${constraintPolicies.length} constraint policy(ies), ${policies.length} row policy(ies)`
|
|
2812
|
+
);
|
|
2657
2813
|
if (verified?.userId) {
|
|
2658
2814
|
const claimedId = message?.payload?.userId;
|
|
2659
2815
|
if (!announcedVerified) {
|
|
@@ -2678,6 +2834,7 @@ function runWithMessageIdentity(message, fn) {
|
|
|
2678
2834
|
role: verified.role,
|
|
2679
2835
|
requestId,
|
|
2680
2836
|
policies,
|
|
2837
|
+
constraintPolicies,
|
|
2681
2838
|
// `?? undefined` so "no restriction" leaves the key off the context
|
|
2682
2839
|
// entirely; `[]` is passed through as the deny-everything it means.
|
|
2683
2840
|
allowedSources: allowedSources ?? void 0,
|
|
@@ -2695,7 +2852,10 @@ function runWithMessageIdentity(message, fn) {
|
|
|
2695
2852
|
"[RequestIdentity] Using the client-supplied payload.userId as the principal \u2014 the relay is not stamping a verified authContext yet, so this identity is NOT trustworthy. Fine for plumbing; do not enable policy enforcement until the relay change lands."
|
|
2696
2853
|
);
|
|
2697
2854
|
}
|
|
2698
|
-
return runAsUser(
|
|
2855
|
+
return runAsUser(
|
|
2856
|
+
{ userId: claimed, requestId, policies, constraintPolicies, allowedSources: allowedSources ?? void 0 },
|
|
2857
|
+
fn
|
|
2858
|
+
);
|
|
2699
2859
|
}
|
|
2700
2860
|
if (!warnedAnonymous) {
|
|
2701
2861
|
warnedAnonymous = true;
|
|
@@ -25310,6 +25470,9 @@ async function pruneRuns(agentDir, keep) {
|
|
|
25310
25470
|
} catch {
|
|
25311
25471
|
}
|
|
25312
25472
|
}
|
|
25473
|
+
function runModel(def, input, ctx, fallback) {
|
|
25474
|
+
return (typeof def.model === "function" ? def.model(input, ctx) : def.model) || fallback;
|
|
25475
|
+
}
|
|
25313
25476
|
async function runCodingAgent(agentId, options = {}) {
|
|
25314
25477
|
const def = getCodingAgent(agentId);
|
|
25315
25478
|
if (!def) {
|
|
@@ -25401,9 +25564,10 @@ async function runCodingAgent(agentId, options = {}) {
|
|
|
25401
25564
|
(runAsJob && def.buildPrompt ? await def.buildPrompt(ws, input, ctx) : outputPath ? `Carry out the task described in ${INSTRUCTIONS_FILE}. Write your finished result to this exact absolute path: ${outputPath}` : `Carry out the task described in ${INSTRUCTIONS_FILE}.`);
|
|
25402
25565
|
const tools = { ...cfg.sharedTools ?? {}, ...def.tools ?? {} };
|
|
25403
25566
|
const sessionEnv = def.env ? await def.env(input, ctx) : void 0;
|
|
25567
|
+
const model = runModel(def, input, ctx, cfg.model);
|
|
25404
25568
|
const session = createCodingAgentSession(def.harness || cfg.harness, {
|
|
25405
25569
|
cwd: dir,
|
|
25406
|
-
model
|
|
25570
|
+
model,
|
|
25407
25571
|
resumeId,
|
|
25408
25572
|
instructionsFile: INSTRUCTIONS_FILE,
|
|
25409
25573
|
// undefined, not {}, when this agent has no tools — see the driver.
|
|
@@ -25490,7 +25654,7 @@ async function runCodingAgent(agentId, options = {}) {
|
|
|
25490
25654
|
logger.warn(`[CodingAgent:${def.id}] deliverable rejected (${message}) \u2014 asking the agent to repair it`);
|
|
25491
25655
|
const repair = createCodingAgentSession(def.harness || cfg.harness, {
|
|
25492
25656
|
cwd: dir,
|
|
25493
|
-
model
|
|
25657
|
+
model,
|
|
25494
25658
|
resumeId: result.sessionId,
|
|
25495
25659
|
instructionsFile: INSTRUCTIONS_FILE,
|
|
25496
25660
|
mcpServers: tools && Object.keys(tools).length ? tools : void 0,
|
|
@@ -30092,6 +30256,7 @@ export {
|
|
|
30092
30256
|
bridgePreamble,
|
|
30093
30257
|
captureContext,
|
|
30094
30258
|
clearContextTokens,
|
|
30259
|
+
constraintPoliciesFromConfig,
|
|
30095
30260
|
contextTokenCount,
|
|
30096
30261
|
createCodexSession,
|
|
30097
30262
|
createCodingAgentSession,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superatomai/sdk-node",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.89-dsp",
|
|
4
4
|
"description": "Node.js TypeScript SDK for Superatom",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"build": "tsc --noEmit && tsup",
|
|
51
51
|
"dev": "tsup --watch",
|
|
52
52
|
"test": "tsx test-sdk.ts",
|
|
53
|
+
"test:unit": "node --import tsx --test tests/unit/*.test.ts",
|
|
53
54
|
"type-check": "tsc --noEmit"
|
|
54
55
|
}
|
|
55
56
|
}
|