@inflexa-ai/harness 0.26.1 → 0.26.2

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.
@@ -12,6 +12,11 @@
12
12
  * The body owns the whole machine lifetime. It creates the container, submits one exec, awaits the terminal
13
13
  * result, and tears the container down on both paths. A teardown fault reaches the log alone, because the
14
14
  * work is done by then.
15
+ *
16
+ * The exec id is `${workflowId}:${stepId}:${fnId}`, the one shape that `workflowIdFromExec` parses. A
17
+ * callback host reads the owner workflow out of the exec id alone, thus a flat id makes the completion
18
+ * callback unroutable and it lands as a `400`. The pull backstop still settles such an exec, but it pays
19
+ * the quiet interval first.
15
20
  */
16
21
  import type { Logger } from "../lib/logger.js";
17
22
  import type { SandboxClient } from "../sandbox/client.js";
@@ -39,8 +44,13 @@ export declare function runDeriveTableExecBody(input: DeriveTableExecInput, deps
39
44
  * dispatches with `DBOS.startWorkflow`.
40
45
  */
41
46
  export declare function registerDeriveTableExecWorkflow(deps: DeriveTableExecDeps): (input: DeriveTableExecInput) => Promise<ExecResult>;
42
- /** The per-attempt workflow id. The execution id is unique already, and the nonce keeps a retry distinct. */
43
- export declare function deriveTableExecWorkflowId(executionId: string, nonce: string): string;
47
+ /**
48
+ * The workflow id of one derivation.
49
+ *
50
+ * It carries exactly one colon, because `workflowIdFromExec` recovers the id by a strip of the last two
51
+ * colon-delimited segments of the exec id. The execution id is unique already, thus no nonce joins it.
52
+ */
53
+ export declare function deriveTableExecWorkflowId(executionId: string): string;
44
54
  /**
45
55
  * The async edge. It starts the registered workflow and it awaits the terminal result.
46
56
  *
@@ -12,9 +12,13 @@
12
12
  * The body owns the whole machine lifetime. It creates the container, submits one exec, awaits the terminal
13
13
  * result, and tears the container down on both paths. A teardown fault reaches the log alone, because the
14
14
  * work is done by then.
15
+ *
16
+ * The exec id is `${workflowId}:${stepId}:${fnId}`, the one shape that `workflowIdFromExec` parses. A
17
+ * callback host reads the owner workflow out of the exec id alone, thus a flat id makes the completion
18
+ * callback unroutable and it lands as a `400`. The pull backstop still settles such an exec, but it pays
19
+ * the quiet interval first.
15
20
  */
16
21
  import { DBOS } from "@dbos-inc/dbos-sdk";
17
- import { randomUUID } from "node:crypto";
18
22
  import { createNoopLogger } from "../lib/console-logger.js";
19
23
  import { mintSandboxIdentity } from "../sandbox/identity.js";
20
24
  import { buildDerivationExec, DERIVATION_DEADLINE_MS, DERIVATION_RESOURCES, DERIVE_RUN_LITERAL, DERIVE_STEP_LITERAL, } from "../tools/report-session/derive-table.js";
@@ -28,7 +32,10 @@ const noopEmit = () => { };
28
32
  */
29
33
  export async function runDeriveTableExecBody(input, deps) {
30
34
  const logger = (deps.logger ?? createNoopLogger()).named("derive-table-exec").with({ analysisId: input.analysisId });
31
- const workflowId = DBOS.workflowID ?? `${DERIVE_RUN_LITERAL}:${input.executionId}`;
35
+ const workflowId = DBOS.workflowID ?? deriveTableExecWorkflowId(input.executionId);
36
+ // One workflow submits one exec, thus the function id is a constant. The three segments are what a
37
+ // callback host parses to find the workflow that awaits this exec.
38
+ const execId = `${workflowId}:${DERIVE_STEP_LITERAL}:fn-0`;
32
39
  const sandbox = await deps.sandboxClient.createSandbox({
33
40
  runId: DERIVE_RUN_LITERAL,
34
41
  stepId: DERIVE_STEP_LITERAL,
@@ -43,12 +50,12 @@ export async function runDeriveTableExecBody(input, deps) {
43
50
  const deadline = (await (deps.now ?? (() => DBOS.now()))()) + DERIVATION_DEADLINE_MS;
44
51
  await deps.sandboxClient.submitExec(sandbox, buildDerivationExec({
45
52
  script: input.script,
46
- execId: input.executionId,
53
+ execId,
47
54
  workingDir: input.workingDir,
48
55
  inputs: input.inputs,
49
56
  output: input.output,
50
57
  }));
51
- return await deps.sandboxClient.awaitExec(sandbox, input.executionId, noopEmit, deadline);
58
+ return await deps.sandboxClient.awaitExec(sandbox, execId, noopEmit, deadline);
52
59
  }
53
60
  finally {
54
61
  try {
@@ -66,9 +73,14 @@ export async function runDeriveTableExecBody(input, deps) {
66
73
  export function registerDeriveTableExecWorkflow(deps) {
67
74
  return DBOS.registerWorkflow((input) => runDeriveTableExecBody(input, deps), { name: "derive-table-exec" });
68
75
  }
69
- /** The per-attempt workflow id. The execution id is unique already, and the nonce keeps a retry distinct. */
70
- export function deriveTableExecWorkflowId(executionId, nonce) {
71
- return `${DERIVE_RUN_LITERAL}:${executionId}:${nonce}`;
76
+ /**
77
+ * The workflow id of one derivation.
78
+ *
79
+ * It carries exactly one colon, because `workflowIdFromExec` recovers the id by a strip of the last two
80
+ * colon-delimited segments of the exec id. The execution id is unique already, thus no nonce joins it.
81
+ */
82
+ export function deriveTableExecWorkflowId(executionId) {
83
+ return `${DERIVE_RUN_LITERAL}:${executionId}`;
72
84
  }
73
85
  /**
74
86
  * The async edge. It starts the registered workflow and it awaits the terminal result.
@@ -78,7 +90,7 @@ export function deriveTableExecWorkflowId(executionId, nonce) {
78
90
  */
79
91
  export async function triggerDeriveTableExec(workflow, input) {
80
92
  const handle = (await DBOS.startWorkflow(workflow, {
81
- workflowID: deriveTableExecWorkflowId(input.executionId, randomUUID()),
93
+ workflowID: deriveTableExecWorkflowId(input.executionId),
82
94
  })(input));
83
95
  return handle.getResult();
84
96
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inflexa-ai/harness",
3
- "version": "0.26.1",
3
+ "version": "0.26.2",
4
4
  "description": "Host-agnostic bioinformatics agent harness — hand-rolled agent loop, DBOS-durable workflows, sandboxed compute.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",