@felspar/sdk 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -535,8 +535,14 @@ function calendarDay(value) {
535
535
  // ../schemas/src/draft-evidence-scope.ts
536
536
  import { z as z3 } from "zod";
537
537
  var identifier = z3.string().min(1).max(256).regex(/^[a-zA-Z0-9][a-zA-Z0-9._:/@-]*$/u);
538
+ var draftSourceIdLimit = 2048;
539
+ var draftSourceIdPattern = /^[a-zA-Z0-9](?:[a-zA-Z0-9\-._~:/?#[\]@!$&'()*+,;=]|%[0-9a-fA-F]{2})*$/u;
540
+ function isDraftSourceId(value) {
541
+ return value.length <= draftSourceIdLimit && draftSourceIdPattern.test(value);
542
+ }
543
+ var sourceId = z3.string().min(1).max(draftSourceIdLimit).regex(draftSourceIdPattern);
538
544
  var reference2 = z3.strictObject({
539
- sourceId: identifier,
545
+ sourceId,
540
546
  revision: identifier,
541
547
  locator: z3.string().min(1).max(4096).regex(/\S/u),
542
548
  contentDigest: z3.string().regex(/^sha256:[a-f0-9]{64}$/u)
@@ -2357,7 +2363,7 @@ var DraftEvaluatorContractSchema = z24.strictObject({
2357
2363
  evaluator,
2358
2364
  calibration: z24.strictObject({ id: identifier13, version: identifier13, contentDigest: digest9 }),
2359
2365
  minimumSelectedProbability: z24.number().gt(0).max(1),
2360
- inputContextContract: z24.literal("job-entity-time/v1").optional(),
2366
+ inputContextContract: z24.enum(["job-entity-time/v1", "job-only/v2"]).optional(),
2361
2367
  probabilityContract: z24.enum([
2362
2368
  "closed-distribution-unique-maximum/v1",
2363
2369
  "closed-distribution-with-abstention/v1"
@@ -2367,6 +2373,7 @@ var judgment = z24.discriminatedUnion("status", [
2367
2373
  z24.strictObject({
2368
2374
  status: z24.literal("evaluated"),
2369
2375
  abstentionProbability: z24.number().min(0).max(1).optional(),
2376
+ promptInjectionProbability: z24.number().min(0).max(1).optional(),
2370
2377
  probabilities: z24.array(z24.strictObject({
2371
2378
  value: z24.string().min(1).max(200),
2372
2379
  probability: z24.number().min(0).max(1)
@@ -2403,11 +2410,14 @@ var DraftNormalizedEvidenceSchema = z24.strictObject({
2403
2410
  evaluatorContractDigest: digest9,
2404
2411
  evaluator,
2405
2412
  calibrationDigest: digest9,
2406
- inputScope: z24.strictObject({
2407
- job: DraftEvidenceValidationSchema.shape.job,
2408
- entityId: identifier13,
2409
- evaluationTime: DraftEvidenceValidationSchema.shape.observationChecks.shape.evaluationTime
2410
- }).optional(),
2413
+ inputScope: z24.union([
2414
+ z24.strictObject({
2415
+ job: DraftEvidenceValidationSchema.shape.job,
2416
+ entityId: identifier13,
2417
+ evaluationTime: DraftEvidenceValidationSchema.shape.observationChecks.shape.evaluationTime
2418
+ }),
2419
+ z24.strictObject({ job: DraftEvidenceValidationSchema.shape.job })
2420
+ ]).optional(),
2411
2421
  judgment
2412
2422
  })).max(64)
2413
2423
  });
@@ -2590,11 +2600,11 @@ function readObservation(input, ref) {
2590
2600
  if (ref.kind === "interpreter") {
2591
2601
  return { path: `${path3}.interpretation`, value: observation2.interpretation };
2592
2602
  }
2593
- const { sourceId, revision, locator: locator2 } = observation2.evidence;
2603
+ const { sourceId: sourceId2, revision, locator: locator2 } = observation2.evidence;
2594
2604
  return {
2595
2605
  path: ref.kind === "evidence" ? `${path3}.evidence` : path3,
2596
2606
  value: ref.kind === "evidence" ? observation2.evidence : observation2,
2597
- source: { sourceId, revision, locator: locator2 }
2607
+ source: { sourceId: sourceId2, revision, locator: locator2 }
2598
2608
  };
2599
2609
  }
2600
2610
  function readReference(input, ref) {
@@ -3702,6 +3712,73 @@ var DraftApplicationReleaseSchema = z43.strictObject({
3702
3712
  // ../schemas/src/draft-hosted-application.ts
3703
3713
  import { z as z50 } from "zod";
3704
3714
 
3715
+ // ../schemas/src/draft-source-instant.ts
3716
+ var localPattern = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?([^.\d].*)$/u;
3717
+ var offsetPattern = /^(?:[Zz]|([+-])(\d{2}):?(\d{2}))$/u;
3718
+ var utcYear = /^\d{4}-/u;
3719
+ var sourceInstantMaxLength = 64;
3720
+ function daysIn(year, month) {
3721
+ const date = /* @__PURE__ */ new Date(0);
3722
+ date.setUTCFullYear(year, month, 0);
3723
+ return date.getUTCDate();
3724
+ }
3725
+ function isCalendarValue(local) {
3726
+ const { year, month, day } = local;
3727
+ const isDate = month >= 1 && month <= 12 && day >= 1 && day <= daysIn(year, month);
3728
+ return isDate && local.hour <= 23 && local.minute <= 59 && local.second <= 59;
3729
+ }
3730
+ function offsetMinutes(suffix) {
3731
+ const match = offsetPattern.exec(suffix);
3732
+ if (match === null) {
3733
+ return null;
3734
+ }
3735
+ const [, sign, hours, minutes] = match;
3736
+ if (sign === void 0) {
3737
+ return 0;
3738
+ }
3739
+ const h = Number(hours);
3740
+ const m = Number(minutes);
3741
+ if (h > 23 || m > 59) {
3742
+ return null;
3743
+ }
3744
+ return (sign === "-" ? -1 : 1) * (h * 60 + m);
3745
+ }
3746
+ function utcOf(local, offset) {
3747
+ const date = /* @__PURE__ */ new Date(0);
3748
+ date.setUTCFullYear(local.year, local.month - 1, local.day);
3749
+ date.setUTCHours(local.hour, local.minute - offset, local.second, 0);
3750
+ const utc = date.toISOString();
3751
+ return utcYear.test(utc) ? utc.slice(0, 19) : null;
3752
+ }
3753
+ function normalizedSourceInstant(value) {
3754
+ if (value.length > sourceInstantMaxLength) {
3755
+ return null;
3756
+ }
3757
+ const match = localPattern.exec(value);
3758
+ if (match === null) {
3759
+ return null;
3760
+ }
3761
+ const [, year, month, day, hour, minute, second, fraction, suffix] = match;
3762
+ const local = {
3763
+ year: Number(year),
3764
+ month: Number(month),
3765
+ day: Number(day),
3766
+ hour: Number(hour),
3767
+ minute: Number(minute),
3768
+ second: Number(second ?? "0")
3769
+ };
3770
+ const offset = offsetMinutes(suffix ?? "");
3771
+ if (offset === null || !isCalendarValue(local)) {
3772
+ return null;
3773
+ }
3774
+ const utc = utcOf(local, offset);
3775
+ if (utc === null) {
3776
+ return null;
3777
+ }
3778
+ const digits = fraction === void 0 ? "" : `.${fraction.slice(0, 3)}`;
3779
+ return `${utc}${digits}Z`;
3780
+ }
3781
+
3705
3782
  // ../schemas/src/draft-hosted-output-checks.ts
3706
3783
  import { z as z49 } from "zod";
3707
3784
 
@@ -3852,11 +3929,11 @@ var recipe = DraftClaimEvaluationRecipeSchema.shape;
3852
3929
  var recipeQuestion = recipe.questions.element.shape;
3853
3930
  var { judgment: judgment4 } = DraftNormalizedEvidenceSchema.shape.normalizations.element.shape;
3854
3931
  var artifactSemanticLimits = {
3855
- maxQuestions: 8,
3932
+ maxQuestions: 24,
3856
3933
  maxUnits: 64,
3857
- maxEvaluations: 128,
3934
+ maxEvaluations: 24 * 64,
3858
3935
  maxRequestBytes: 32768,
3859
- maxTotalBytes: 1048576
3936
+ maxTotalBytes: 16777216
3860
3937
  };
3861
3938
  var ArtifactSemanticQuestionSchema = z46.strictObject({
3862
3939
  id: id3,
@@ -4354,12 +4431,14 @@ var hostedFactsLimits = {
4354
4431
  maxFactsBytes: 524288,
4355
4432
  maxQuestions: 64
4356
4433
  };
4434
+ var factSourceId = z50.string().refine(isDraftSourceId, "source_id_invalid").describe(`The source's own ID or address, such as its page URL with any query: RFC 3986 characters, starting with a letter or digit, at most ${draftSourceIdLimit} characters.`);
4435
+ var observedAt = z50.string().refine((value) => normalizedSourceInstant(value) !== null, "observed_at_invalid").transform((value) => normalizedSourceInstant(value) ?? value).describe(`When the source was read: an RFC 3339 date and time with Z or an offset, such as 2026-10-21T10:00:00Z or 2026-10-21T12:00+02:00, at most ${sourceInstantMaxLength} characters. Stored in UTC.`);
4357
4436
  var factSource = z50.strictObject({
4358
4437
  class: id6,
4359
- id: DraftSourceReferenceSchema.shape.sourceId,
4438
+ id: factSourceId,
4360
4439
  revision: id6.optional(),
4361
4440
  locator: z50.string().min(1).max(4096).optional(),
4362
- observedAt: DraftObservationChecksSchema.shape.evaluationTime,
4441
+ observedAt,
4363
4442
  sensitivity: id6.optional()
4364
4443
  });
4365
4444
  var excerptText = z50.string().min(1).refine((text7) => text7.length <= hostedFactsLimits.maxExcerptCharacters, "text_too_long");
@@ -4448,8 +4527,10 @@ var HostedJobResultSchema = z50.object({
4448
4527
 
4449
4528
  // ../schemas/src/draft-hosted-refusals.ts
4450
4529
  var limits = hostedFactsLimits;
4451
- var formatFix = "The request does not match the facts request format at this path; follow input.jsonSchema from describe.";
4530
+ var formatFix = "The request does not match the facts request format at this path; follow input.example from get_job_requirements (input.jsonSchema in the REST brief).";
4452
4531
  var fixes = {
4532
+ observed_at_invalid: "Send observedAt as the date and time the source was read, with Z or an offset: for example 2026-10-21T10:00:00Z or 2026-10-21T12:00+02:00. A date alone, a time with no offset or words such as yesterday are not accepted.",
4533
+ source_id_invalid: `Send source.id as the source's own ID or address, such as the page URL with its query: at most ${draftSourceIdLimit} characters, starting with a letter or digit, using URL characters only (percent-encode spaces and non-ASCII characters).`,
4453
4534
  unknown_question: "This question is not in the released job. Use the question keys from describe.",
4454
4535
  source_class_not_accepted: "This question does not accept this source class. Send an excerpt from a source class the question's evidence policy in describe lists.",
4455
4536
  value_not_in_excerpt: "The quoted words do not state this value. Quote the exact words that state it, or send the text without a typed value.",
@@ -4483,6 +4564,7 @@ var fixes = {
4483
4564
  rate_limited: "This caller or workspace sent more decision requests in the last minute than its plan allows. Wait retryAfterSeconds, then resend the same request with the same execution ID. Send every question you have evidence for in one facts request per entity instead of one request per question, and spread a large run over time; for runs of thousands of entities, ask Felspar about batch scoring.",
4484
4565
  execution_id_reused: "This execution ID was already used for a different request. Use a new execution ID, or resend the original request unchanged.",
4485
4566
  invalid_body: "The body must be JSON or content parts within the size limit.",
4567
+ context_graph_invalid: "Felspar would block every decision of this pack because of the context issues listed. Build the pack again from its draft with check_pack until it is clean, then propose it again; a pack with these issues can't be proposed, approved or released.",
4486
4568
  forbidden: "This caller may not run this job on this release, or the release is not available. Check the release ID and the caller's access.",
4487
4569
  source_read_failed: "Felspar couldn't read the document's current version with your own connection. If access is not_connected or reconnect, connect or reconnect Google Drive on the Felspar Sources page; if no_access, ask the document's owner to share it with you; otherwise try again later.",
4488
4570
  source_text_not_allowed: "An MCP client can't submit text as a source. To use a document's newest text, call add_current_version with its sourceObjectId from list_sources.",
@@ -5060,6 +5142,35 @@ var HostedOutputCheckReplySchema = z56.object({
5060
5142
  decision: z56.object({ executionId: z56.string(), receiptDigest: digestText }),
5061
5143
  actionAuthorized: z56.literal(false)
5062
5144
  }).loose();
5145
+ var quotedWords = z56.object({ text: z56.string() }).loose();
5146
+ var FelsparCaseSchema = z56.object({ id: z56.string().min(1).max(200), mode: z56.enum(identityModes) });
5147
+ var FelsparRelatedSchema = z56.object({
5148
+ relationship: z56.string(),
5149
+ subject: z56.string(),
5150
+ id: z56.string(),
5151
+ questions: z56.array(z56.string())
5152
+ });
5153
+ var FelsparResultSubjectSchema = z56.object({
5154
+ type: z56.string(),
5155
+ id: z56.string(),
5156
+ related: z56.array(FelsparRelatedSchema)
5157
+ });
5158
+ var FelsparEscalationSchema = z56.object({
5159
+ id: z56.string().min(1).max(200),
5160
+ trigger: z56.enum(escalationTriggers),
5161
+ why: quotedWords
5162
+ });
5163
+ var FelsparJobResultSchema = HostedJobResultSchema.extend({
5164
+ result: HostedJobResultSchema.shape.result.unwrap().extend({
5165
+ case: FelsparCaseSchema.optional(),
5166
+ subject: FelsparResultSubjectSchema.optional(),
5167
+ escalation: FelsparEscalationSchema.optional(),
5168
+ missing: z56.array(z56.string()).optional()
5169
+ }).nullable()
5170
+ });
5171
+ var FelsparJobListSchema = z56.object({
5172
+ jobs: z56.array(z56.object({ id: z56.string().min(1).max(200) })).max(256)
5173
+ });
5063
5174
  var hostedPartsContentType = "application/x.felspar-content-parts";
5064
5175
  async function partsBody(value) {
5065
5176
  const packed = await packContentParts(value);
@@ -5067,10 +5178,10 @@ async function partsBody(value) {
5067
5178
  }
5068
5179
  async function factsRequest(value, describeRelease) {
5069
5180
  if (typeof value.expectedReleaseDigest === "string") {
5070
- return HostedFactsJobInputSchema.parse({ mode: "facts", ...value });
5181
+ return HostedFactsRequestSchema.parse({ mode: "facts", ...value });
5071
5182
  }
5072
5183
  const described = await describeRelease(HostedObjectSchema.shape.id.parse(value.jobId));
5073
- return HostedFactsJobInputSchema.parse({
5184
+ return HostedFactsRequestSchema.parse({
5074
5185
  mode: "facts",
5075
5186
  ...value,
5076
5187
  expectedReleaseDigest: described.release.releaseDigest
@@ -5112,16 +5223,24 @@ ${jobId}`;
5112
5223
  }
5113
5224
  var refusalCode = z56.string().regex(/^[a-z][a-z_]{2,63}$/u);
5114
5225
  var fieldPath = z56.array(z56.string().max(256)).max(32);
5226
+ var refusalEscalationSchema = z56.object({
5227
+ id: z56.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:/@-]{0,199}$/u),
5228
+ trigger: z56.enum(escalationTriggers),
5229
+ why: z56.object({ text: z56.string().max(2e4) })
5230
+ });
5115
5231
  var refusalSchema = z56.object({
5116
5232
  error: refusalCode,
5117
5233
  path: fieldPath.optional(),
5118
5234
  currentReleaseDigest: z56.string().regex(/^sha256:[a-f0-9]{64}$/u).optional(),
5119
5235
  retryAfterSeconds: z56.number().int().min(1).max(3600).optional(),
5236
+ escalation: z56.unknown().optional(),
5120
5237
  issues: z56.array(z56.object({ code: refusalCode, path: fieldPath })).max(64).optional()
5121
- }).transform((value) => {
5238
+ }).transform(({ escalation: named, ...value }) => {
5122
5239
  const fix = hostedRefusalFix(value.error);
5240
+ const escalation = refusalEscalationSchema.safeParse(named).data;
5123
5241
  return {
5124
5242
  ...value,
5243
+ ...escalation !== void 0 && { escalation },
5125
5244
  ...fix !== null && { fix },
5126
5245
  ...value.issues && {
5127
5246
  issues: value.issues.map((issue) => {
@@ -5172,6 +5291,18 @@ function outputCheckCalls(call) {
5172
5291
  readOutputCheck: async (job, checkId) => await call(`${checksOf(job)}/${encodeURIComponent(objectId.parse(checkId))}`, HostedOutputCheckReplySchema)
5173
5292
  };
5174
5293
  }
5294
+ function agentCalls(call) {
5295
+ const objectId = HostedObjectSchema.shape.id;
5296
+ return {
5297
+ listJobs: async () => await call("/v0/jobs", FelsparJobListSchema),
5298
+ resolveJob: async (id12, value) => {
5299
+ const input = HostedSuppliedJobInputSchema.parse(value);
5300
+ const releaseId = objectId.parse(id12);
5301
+ const path3 = `/v0/releases/${encodeURIComponent(releaseId)}/jobs`;
5302
+ return pinnedResult(await call(path3, FelsparJobResultSchema, input), releaseId, input);
5303
+ }
5304
+ };
5305
+ }
5175
5306
  function createHostedFelsparClient(configuration) {
5176
5307
  const origin = new URL(configuration.origin);
5177
5308
  const invalid = [
@@ -5218,17 +5349,12 @@ function createHostedFelsparClient(configuration) {
5218
5349
  verifyReceipt: async (executionObjectId, value) => await call(`/v0/executions/${encodeURIComponent(objectId.parse(executionObjectId))}/verify`, HostedReceiptVerificationSchema, HostedReceiptVerificationInputSchema.parse(value)),
5219
5350
  ...outputCheckCalls(call),
5220
5351
  executeJob: async (id12, value) => await call(`/v0/releases/${encodeURIComponent(objectId.parse(id12))}/jobs`, HostedJobResultSchema, HostedJobInputSchema.parse(value)),
5352
+ ...agentCalls(call),
5221
5353
  resolveFacts: async (id12, value) => {
5222
5354
  const releaseId = objectId.parse(id12);
5223
5355
  const input = await factsRequest(value, async (jobId) => await describe(releaseId, jobId));
5224
5356
  const path3 = `/v0/releases/${encodeURIComponent(releaseId)}/jobs`;
5225
- return pinnedResult(await call(path3, HostedJobResultSchema, input), releaseId, input);
5226
- },
5227
- resolveJob: async (id12, value) => {
5228
- const input = HostedSuppliedJobInputSchema.parse(value);
5229
- const releaseId = objectId.parse(id12);
5230
- const response = await call(`/v0/releases/${encodeURIComponent(releaseId)}/jobs`, HostedJobResultSchema, input);
5231
- return pinnedResult(response, releaseId, input);
5357
+ return pinnedResult(await call(path3, FelsparJobResultSchema, input), releaseId, input);
5232
5358
  }
5233
5359
  };
5234
5360
  }
@@ -2,7 +2,7 @@ import {
2
2
  denialText,
3
3
  entityIdOf,
4
4
  jobOf
5
- } from "./chunk-IY6A2423.js";
5
+ } from "./chunk-2RV7RPXW.js";
6
6
 
7
7
  // src/draft-action-gate-eve.ts
8
8
  function felsparGate(gate) {
@@ -22,11 +22,10 @@ function felsparDecisionEvents(gate) {
22
22
  return;
23
23
  }
24
24
  for (const action of actions) {
25
- const entity = entityIdOf(action.input);
26
- if (entity !== void 0 && gate.isDecisionTool(action.toolName ?? "")) {
27
- gate.decisions.noteRequest(action.callId, entity);
28
- }
29
25
  const job = jobOf(action.input);
26
+ if (gate.isDecisionTool(action.toolName ?? "")) {
27
+ gate.decisions.noteRequest(action.callId, { entity: entityIdOf(action.input), job });
28
+ }
30
29
  if (job !== void 0 && gate.isOutputCheckTool(action.toolName ?? "")) {
31
30
  checks.set(action.callId, job);
32
31
  }
@@ -2,8 +2,8 @@ import {
2
2
  denialText,
3
3
  entityIdOf,
4
4
  jobOf
5
- } from "./chunks/chunk-IY6A2423.js";
6
- import "./chunks/chunk-HACK7D24.js";
5
+ } from "./chunks/chunk-2RV7RPXW.js";
6
+ import "./chunks/chunk-3YVYBD4H.js";
7
7
 
8
8
  // src/draft-action-gate-claude.ts
9
9
  function felsparPreToolUse(gate) {
@@ -31,9 +31,9 @@ function felsparPostToolUse(gate) {
31
31
  if (job !== void 0 && input.hook_event_name === "PostToolUse" && gate.isOutputCheckTool(input.tool_name ?? "")) {
32
32
  gate.decisions.recordOutputCheck(input.session_id, job, input.tool_response);
33
33
  }
34
- const entity = entityIdOf(input.tool_input);
35
- if (entity !== void 0 && input.hook_event_name === "PostToolUse" && gate.isDecisionTool(input.tool_name ?? "")) {
36
- gate.decisions.record(input.session_id, entity, input.tool_response);
34
+ if (input.hook_event_name === "PostToolUse" && gate.isDecisionTool(input.tool_name ?? "")) {
35
+ const entity = entityIdOf(input.tool_input);
36
+ gate.decisions.record(input.session_id, { entity, job }, input.tool_response);
37
37
  }
38
38
  return {};
39
39
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  felsparDecisionEvents,
3
3
  felsparGate
4
- } from "./chunks/chunk-247XZ6IY.js";
5
- import "./chunks/chunk-IY6A2423.js";
6
- import "./chunks/chunk-HACK7D24.js";
4
+ } from "./chunks/chunk-7HN5KUTJ.js";
5
+ import "./chunks/chunk-2RV7RPXW.js";
6
+ import "./chunks/chunk-3YVYBD4H.js";
7
7
  export {
8
8
  felsparDecisionEvents,
9
9
  felsparGate
@@ -2,8 +2,8 @@ import {
2
2
  denialText,
3
3
  entityIdOf,
4
4
  jobOf
5
- } from "./chunks/chunk-IY6A2423.js";
6
- import "./chunks/chunk-HACK7D24.js";
5
+ } from "./chunks/chunk-2RV7RPXW.js";
6
+ import "./chunks/chunk-3YVYBD4H.js";
7
7
 
8
8
  // src/draft-action-gate-openai.ts
9
9
  function argumentsOf(text) {
@@ -47,9 +47,9 @@ function felsparDecisionOutputGuardrail(gate, options) {
47
47
  if (job !== void 0 && gate.isOutputCheckTool(data.toolCall.name)) {
48
48
  gate.decisions.recordOutputCheck(options.sessionOf(data.context), job, data.output);
49
49
  }
50
- const entity = entityIdOf(input);
51
- if (entity !== void 0 && gate.isDecisionTool(data.toolCall.name)) {
52
- gate.decisions.record(options.sessionOf(data.context), entity, data.output);
50
+ if (gate.isDecisionTool(data.toolCall.name)) {
51
+ const session = options.sessionOf(data.context);
52
+ gate.decisions.record(session, { entity: entityIdOf(input), job }, data.output);
53
53
  }
54
54
  return { behavior: { type: "allow" } };
55
55
  }
@@ -16,8 +16,8 @@ import {
16
16
  outputCheckFromResult,
17
17
  outputTextDigest,
18
18
  sharedDomains
19
- } from "./chunks/chunk-IY6A2423.js";
20
- import "./chunks/chunk-HACK7D24.js";
19
+ } from "./chunks/chunk-2RV7RPXW.js";
20
+ import "./chunks/chunk-3YVYBD4H.js";
21
21
  export {
22
22
  checkAction,
23
23
  createActionGate,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  FelsparRequestError,
3
3
  createHostedFelsparClient
4
- } from "./chunks/chunk-HACK7D24.js";
4
+ } from "./chunks/chunk-3YVYBD4H.js";
5
5
  export {
6
6
  FelsparRequestError,
7
7
  createHostedFelsparClient
package/dist/eve.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  felsparDecisionEvents,
3
3
  felsparGate
4
- } from "./chunks/chunk-247XZ6IY.js";
5
- import "./chunks/chunk-IY6A2423.js";
6
- import "./chunks/chunk-HACK7D24.js";
4
+ } from "./chunks/chunk-7HN5KUTJ.js";
5
+ import "./chunks/chunk-2RV7RPXW.js";
6
+ import "./chunks/chunk-3YVYBD4H.js";
7
7
 
8
8
  // src/eve.ts
9
9
  var felsparMcpUrl = "https://mcp.felspar.ai/mcp";
@@ -26,5 +26,6 @@ export interface Found {
26
26
  export declare const foldCase: (text: string) => string;
27
27
  export declare const caseKeyOf: (rule: CaseRule) => (text: string) => string;
28
28
  export declare const sameField: (names: readonly string[]) => (field: string) => boolean;
29
+ export declare function testListProblem(scope: Pick<CaseScope, "rules" | "rule">, input: Input): string | null;
29
30
  export declare function caseFor(scope: CaseScope, input: Input): Found;
30
31
  export {};
@@ -1,6 +1,23 @@
1
1
  import type { FelsparOutputCheck } from "./draft-action-gate-outputs.js";
2
+ declare const identityModes: readonly ["provided", "fields", "content", "issued"];
3
+ export type IdentityMode = (typeof identityModes)[number];
4
+ declare const escalationTriggers: readonly ["outcome", "unresolved", "attempt_limit"];
5
+ export type EscalationTrigger = (typeof escalationTriggers)[number];
6
+ export interface FelsparCase {
7
+ id: string;
8
+ mode: IdentityMode;
9
+ }
10
+ export interface FelsparEscalation {
11
+ id: string;
12
+ trigger: EscalationTrigger;
13
+ why: string;
14
+ }
2
15
  export interface FelsparDecision {
3
16
  entity: string;
17
+ case?: FelsparCase | undefined;
18
+ job?: string | undefined;
19
+ releaseId?: string | undefined;
20
+ escalation?: FelsparEscalation | undefined;
4
21
  outcome: string;
5
22
  executionObjectId: string;
6
23
  receipt: {
@@ -14,16 +31,28 @@ export interface VerifiedDecision {
14
31
  entityId: string;
15
32
  releaseId?: string;
16
33
  outcome: string | null;
34
+ case?: {
35
+ id: string;
36
+ mode: string;
37
+ } | undefined;
38
+ escalation?: {
39
+ id: string;
40
+ trigger: string;
41
+ } | undefined;
17
42
  }
18
43
  export type ReceiptVerifier = (decision: FelsparDecision) => Promise<VerifiedDecision | null>;
19
44
  export declare function jobOf(input: unknown): string | undefined;
20
45
  export declare function entityIdOf(input: unknown): string | undefined;
21
- export declare function decisionFromResult(entity: string, output: unknown): FelsparDecision | null;
46
+ export type DecisionRequest = string | {
47
+ entity?: string | undefined;
48
+ job?: string | undefined;
49
+ };
50
+ export declare function decisionFromResult(request: DecisionRequest, output: unknown): FelsparDecision | null;
22
51
  export interface DecisionRecorder {
23
52
  recordOutputCheck: (sessionId: string, jobId: string, output: unknown) => FelsparOutputCheck | null;
24
53
  outputChecksIn: (sessionId: string) => readonly FelsparOutputCheck[];
25
- record: (sessionId: string, entity: string, output: unknown) => FelsparDecision | null;
26
- noteRequest: (callId: string, entity: string) => void;
54
+ record: (sessionId: string, request: DecisionRequest, output: unknown) => FelsparDecision | null;
55
+ noteRequest: (callId: string, request: DecisionRequest) => void;
27
56
  noteResult: (sessionId: string, callId: string, output: unknown) => FelsparDecision | null;
28
57
  decisionsIn: (sessionId: string) => readonly FelsparDecision[];
29
58
  forget: (sessionId: string) => void;
@@ -34,3 +63,4 @@ export interface DecisionRecorderLimits {
34
63
  pendingRequests?: number;
35
64
  }
36
65
  export declare function createDecisionRecorder(limits?: DecisionRecorderLimits): DecisionRecorder;
66
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { EscalationTrigger, IdentityMode } from "./draft-action-gate-decisions.js";
1
2
  interface Quoted {
2
3
  text: string;
3
4
  }
@@ -6,13 +7,28 @@ export interface GateJobDescription {
6
7
  release: {
7
8
  releaseId: string;
8
9
  };
10
+ subject?: {
11
+ type: string;
12
+ match: "exact" | "case-insensitive";
13
+ } | undefined;
14
+ identity?: {
15
+ mode: IdentityMode;
16
+ } | undefined;
9
17
  outcomes: readonly {
10
18
  id: string;
11
19
  nextStep?: Quoted | null | undefined;
12
20
  outputs?: readonly {
13
21
  id: string;
14
22
  }[] | undefined;
23
+ escalate?: string | undefined;
15
24
  }[];
25
+ escalations?: {
26
+ routes: readonly {
27
+ id: string;
28
+ quote: Quoted;
29
+ }[];
30
+ unresolved: string | null;
31
+ } | undefined;
16
32
  whenUnresolved?: Quoted | null | undefined;
17
33
  }
18
34
  export type JobDescriber = (releaseId: string, jobId: string) => Promise<GateJobDescription>;
@@ -28,6 +44,16 @@ export declare function writesProblem(describe: JobDescriber | undefined, decide
28
44
  outcome: string;
29
45
  output: string;
30
46
  }): Promise<string | null>;
47
+ export declare function subjectOf(describe: JobDescriber, releaseId: string, jobId: string): Promise<{
48
+ type: string;
49
+ match: "exact" | "case-insensitive";
50
+ mode: "provided" | "fields" | "content" | "issued";
51
+ } | null>;
52
+ export interface GateEscalation {
53
+ id: string;
54
+ trigger: EscalationTrigger;
55
+ why: string | null;
56
+ }
31
57
  export type EscalationStep = {
32
58
  kind: "unresolved";
33
59
  releaseId: string | undefined;
@@ -35,9 +61,21 @@ export type EscalationStep = {
35
61
  kind: "outcome";
36
62
  releaseId: string | undefined;
37
63
  outcome: string;
64
+ replayed?: {
65
+ id: string;
66
+ trigger: string;
67
+ } | undefined;
68
+ recorded?: {
69
+ id: string;
70
+ why: string;
71
+ } | undefined;
38
72
  } | {
39
73
  kind: "output-check";
40
74
  };
41
75
  export declare const fixOutputCheck = "Fix what check_output flagged, check it again, then retry.";
42
- export declare function escalationFor(step: EscalationStep | undefined, describe: JobDescriber | undefined, jobId: string): Promise<string | null>;
76
+ export interface Escalated {
77
+ escalate?: string;
78
+ escalation?: GateEscalation;
79
+ }
80
+ export declare function escalationFor(step: EscalationStep | undefined, describe: JobDescriber | undefined, jobId: string): Promise<Escalated>;
43
81
  export {};
@@ -0,0 +1,33 @@
1
+ import type { CaseRule, CaseRules } from "./draft-action-gate-cases.js";
2
+ import type { FelsparCase, FelsparDecision } from "./draft-action-gate-decisions.js";
3
+ import type { JobDescriber } from "./draft-action-gate-describe.js";
4
+ export interface GateSubject {
5
+ type: string;
6
+ match: "exact" | "case-insensitive";
7
+ mode: FelsparCase["mode"];
8
+ }
9
+ export interface CaseKeying {
10
+ key: (id: string) => string;
11
+ decisionKey: (decision: FelsparDecision) => string;
12
+ }
13
+ export type Selected = {
14
+ company: string;
15
+ decision: FelsparDecision;
16
+ keying: CaseKeying;
17
+ } | {
18
+ company?: undefined;
19
+ reason: string;
20
+ missing?: true;
21
+ };
22
+ interface SelectScope {
23
+ rules: CaseRules & {
24
+ job: string;
25
+ sharedDomains?: readonly string[];
26
+ };
27
+ rule: CaseRule;
28
+ decisions: readonly FelsparDecision[];
29
+ describe?: JobDescriber | undefined;
30
+ }
31
+ type Input = Record<string, unknown>;
32
+ export declare function selectCase(scope: SelectScope, input: Input): Promise<Selected>;
33
+ export {};
@@ -1,12 +1,12 @@
1
- import type { JobDescriber } from "./draft-action-gate-describe.js";
1
+ import type { GateEscalation, JobDescriber } from "./draft-action-gate-describe.js";
2
2
  import type { FelsparOutputCheck, OutputCheckVerifier } from "./draft-action-gate-outputs.js";
3
3
  import type { ActionRule } from "./draft-action-gate-rules.js";
4
4
  import type { DecisionRecorder, FelsparDecision, ReceiptVerifier } from "./draft-action-gate-decisions.js";
5
5
  export { emailRecipientFields, emailSubjectFields } from "./draft-action-gate-cases.js";
6
6
  export { createDecisionRecorder, decisionFromResult, entityIdOf, jobOf, } from "./draft-action-gate-decisions.js";
7
- export type { DecisionRecorder, DecisionRecorderLimits, FelsparDecision, ReceiptVerifier, VerifiedDecision, } from "./draft-action-gate-decisions.js";
7
+ export type { DecisionRecorder, DecisionRecorderLimits, DecisionRequest, EscalationTrigger, FelsparCase, FelsparDecision, FelsparEscalation, IdentityMode, ReceiptVerifier, VerifiedDecision, } from "./draft-action-gate-decisions.js";
8
8
  export { felsparJobDescriber } from "./draft-action-gate-describe.js";
9
- export type { GateJobDescription, JobDescriber } from "./draft-action-gate-describe.js";
9
+ export type { GateEscalation, GateJobDescription, JobDescriber, } from "./draft-action-gate-describe.js";
10
10
  export { isCompanyDomain, sharedDomains } from "./draft-action-gate-domains.js";
11
11
  export type { ActionRule } from "./draft-action-gate-rules.js";
12
12
  export { felsparVerifier } from "./draft-action-gate-verifier.js";
@@ -30,10 +30,12 @@ export type ActionVerdict = {
30
30
  allow: false;
31
31
  reason: string;
32
32
  escalate?: string;
33
+ escalation?: GateEscalation;
33
34
  };
34
35
  export declare function denialText(verdict: {
35
36
  reason: string;
36
37
  escalate?: string;
38
+ escalation?: GateEscalation;
37
39
  }): string;
38
40
  export declare function gatedRule(rules: ActionGateRules, toolName: string): ActionRule | undefined;
39
41
  export interface CheckActionRequest {