@shivaedev/agent-codex 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.
Files changed (37) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/adapters/backend.d.ts +5 -0
  3. package/dist/adapters/backend.d.ts.map +1 -0
  4. package/dist/adapters/backend.js +23 -0
  5. package/dist/adapters/backend.js.map +1 -0
  6. package/dist/adapters/census.d.ts +4 -0
  7. package/dist/adapters/census.d.ts.map +1 -0
  8. package/dist/adapters/census.js +10 -0
  9. package/dist/adapters/census.js.map +1 -0
  10. package/dist/adapters/configuredBackend.d.ts +6 -0
  11. package/dist/adapters/configuredBackend.d.ts.map +1 -0
  12. package/dist/adapters/configuredBackend.js +3 -0
  13. package/dist/adapters/configuredBackend.js.map +1 -0
  14. package/dist/adapters/engine.d.ts +3 -5
  15. package/dist/adapters/engine.d.ts.map +1 -1
  16. package/dist/adapters/engine.js +6 -77
  17. package/dist/adapters/engine.js.map +1 -1
  18. package/dist/adapters/initializeCodex.d.ts +770 -0
  19. package/dist/adapters/initializeCodex.d.ts.map +1 -0
  20. package/dist/adapters/initializeCodex.js +8 -0
  21. package/dist/adapters/initializeCodex.js.map +1 -0
  22. package/dist/adapters/initializeEngine.d.ts +774 -0
  23. package/dist/adapters/initializeEngine.d.ts.map +1 -0
  24. package/dist/adapters/initializeEngine.js +63 -0
  25. package/dist/adapters/initializeEngine.js.map +1 -0
  26. package/dist/codex.d.ts +2 -2
  27. package/dist/codex.d.ts.map +1 -1
  28. package/dist/codex.js +7 -7
  29. package/dist/codex.js.map +1 -1
  30. package/package.json +7 -7
  31. package/src/adapters/backend.ts +29 -0
  32. package/src/adapters/census.ts +17 -0
  33. package/src/adapters/configuredBackend.ts +6 -0
  34. package/src/adapters/engine.ts +7 -97
  35. package/src/adapters/initializeCodex.ts +8 -0
  36. package/src/adapters/initializeEngine.ts +75 -0
  37. package/src/codex.ts +7 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initializeEngine.d.ts","sourceRoot":"","sources":["../../src/adapters/initializeEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAa,MAAM,QAAQ,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,eAAO,MAAM,gBAAgB,8CAA4F,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAyD/G,OAAO;;;;;;;mBACX,MAAM,UAAU,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAhBf,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;KAAE,YAAY;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;mLAqBjI,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { Effect, Semaphore } from "effect";
2
+ import { Rejected, UnknownAcceptance } from "@shivaedev/agent/failures.ts";
3
+ import { features } from "#adapters/features.ts";
4
+ import { observe, readRequest } from "#adapters/reads.ts";
5
+ import { receiptOf, recovery } from "#adapters/recovery.ts";
6
+ import { AppServer, openServer } from "#adapters/server.ts";
7
+ import { openSession } from "#adapters/session.ts";
8
+ export const initializeEngine = Effect.fn("Codex.initializeEngine")(function* (config, spawn) {
9
+ const server = yield* openServer(config, spawn);
10
+ const sessions = new Map();
11
+ const { operations, refusals, reconcile } = yield* recovery(sessions).pipe(Effect.provideService(AppServer, server));
12
+ const submissionGate = yield* Semaphore.make(1);
13
+ const submit = Effect.fn("Codex.submit")(function* (request, reference) {
14
+ if (operations.has(request.operationId)) {
15
+ const result = yield* reconcile(request.operationId);
16
+ if (result.type === "accepted") {
17
+ return result.receipt;
18
+ }
19
+ if (result.type === "not-accepted") {
20
+ return yield* new Rejected({ backend: "codex", message: result.evidence });
21
+ }
22
+ return yield* new UnknownAcceptance({
23
+ backend: "codex",
24
+ message: result.reason,
25
+ operationId: request.operationId,
26
+ });
27
+ }
28
+ if (reference !== undefined && (reference.version !== 1 || server.claims.isNode(reference.value))) {
29
+ return yield* new Rejected({ backend: "codex", message: "Child threads are observed passively and cannot be resumed" });
30
+ }
31
+ operations.set(request.operationId, reference?.value);
32
+ const session = yield* openSession(config, request, reference?.value, (operationId, threadId) => {
33
+ operations.set(operationId, threadId);
34
+ }).pipe(Effect.provideService(AppServer, server));
35
+ operations.set(request.operationId, session.threadId);
36
+ sessions.set(session.threadId, session);
37
+ yield* Effect.addFinalizer(() => Effect.sync(() => {
38
+ if (sessions.get(session.threadId) === session) {
39
+ sessions.delete(session.threadId);
40
+ }
41
+ }));
42
+ const turnId = yield* session.driver.start(request.input, request.operationId);
43
+ return receiptOf(request.operationId, session.threadId, turnId);
44
+ });
45
+ function start(request, session) {
46
+ return Semaphore.withPermit(submissionGate)(submit(request, session)).pipe(Effect.tapError((error) => Effect.sync(() => {
47
+ if (error._tag === "Rejected") {
48
+ refusals.set(request.operationId, error.message);
49
+ }
50
+ })));
51
+ }
52
+ return {
53
+ claims: server.claims,
54
+ exited: server.exited,
55
+ features: yield* features(sessions, start).pipe(Effect.provideService(AppServer, server)),
56
+ inspect: (receipt) => observe(receipt).pipe(Effect.provideService(AppServer, server)),
57
+ read: (method, params) => readRequest(method, params).pipe(Effect.provideService(AppServer, server)),
58
+ reconcile,
59
+ sessions,
60
+ start,
61
+ };
62
+ });
63
+ //# sourceMappingURL=initializeEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initializeEngine.js","sourceRoot":"","sources":["../../src/adapters/initializeEngine.ts"],"names":[],"mappings":"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"}
package/dist/codex.d.ts CHANGED
@@ -2,8 +2,8 @@ import { Effect, Layer } from "effect";
2
2
  import { Backend } from "@shivaedev/agent/backend.ts";
3
3
  import { CodexConfig } from "#config.ts";
4
4
  export declare const Codex: import("effect/Context").Service<"@shivaedev/agent-codex/Codex", Readonly<{
5
- backend: () => Effect.Effect<import("@shivaedev/agent/backend.ts").ConfiguredBackend, never, never>;
6
- census: (rootThreadId: string) => Effect.Effect<import("./adapters/threadSweep.ts").CensusSweep, import("@shivaedev/agent/failures.ts").ReadFailure, never>;
5
+ readonly backend: () => Effect.Effect<import("@shivaedev/agent/backend.ts").ConfiguredBackend, never, never>;
6
+ readonly census: (rootThreadId: string) => Effect.Effect<import("./adapters/threadSweep.ts").CensusSweep, import("@shivaedev/agent/failures.ts").ReadFailure, never>;
7
7
  }>> & {
8
8
  readonly layer: Layer.Layer<"@shivaedev/agent-codex/Codex", import("@shivaedev/agent/failures.ts").BackendUnavailable | import("@shivaedev/agent/failures.ts").ProtocolFailure | import("@shivaedev/agent/failures.ts").Rejected | import("@shivaedev/agent/failures.ts").UnknownAcceptance, CodexConfig>;
9
9
  };
@@ -1 +1 @@
1
- {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../src/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAGtD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,eAAO,MAAM,KAAK;;;;;CAQhB,CAAC;AACH,eAAO,MAAM,UAAU,qSAAiH,CAAC"}
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../src/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAMtD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,eAAO,MAAM,KAAK;;;;;CAKhB,CAAC;AACH,eAAO,MAAM,UAAU,qSAAwG,CAAC"}
package/dist/codex.js CHANGED
@@ -1,16 +1,16 @@
1
1
  import { Effect, Layer } from "effect";
2
2
  import { Backend } from "@shivaedev/agent/backend.ts";
3
3
  import { defineService } from "@shivaedev/service/defineService.ts";
4
- import { engine } from "#adapters/engine.ts";
4
+ import { backend } from "#adapters/backend.ts";
5
+ import { census } from "#adapters/census.ts";
6
+ import { configuredBackend } from "#adapters/configuredBackend.ts";
7
+ import { initializeCodex } from "#adapters/initializeCodex.ts";
5
8
  import { CodexConfig } from "#config.ts";
6
9
  export const Codex = defineService({
7
10
  id: "@shivaedev/agent-codex/Codex",
8
- initialize: Effect.gen(function* () {
9
- const config = yield* CodexConfig;
10
- return yield* engine(config);
11
- }),
12
- methods: (state) => state,
11
+ initialize: initializeCodex,
12
+ methods: (state) => ({ backend: backend(state), census: census(state) }),
13
13
  requires: [CodexConfig],
14
14
  });
15
- export const codexLayer = Layer.effect(Backend)(Effect.flatMap(Codex, (codex) => codex.backend())).pipe(Layer.provideMerge(Codex.layer));
15
+ export const codexLayer = Layer.effect(Backend)(Effect.flatMap(Codex, configuredBackend)).pipe(Layer.provideMerge(Codex.layer));
16
16
  //# sourceMappingURL=codex.js.map
package/dist/codex.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"codex.js","sourceRoot":"","sources":["../src/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,MAAM,CAAC,MAAM,KAAK,GAAG,aAAa,CAAC;IAClC,EAAE,EAAE,8BAA8B;IAClC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC;QAClC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC,CAAC;IACF,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;IACzB,QAAQ,EAAE,CAAC,WAAW,CAAC;CACvB,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../src/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,MAAM,CAAC,MAAM,KAAK,GAAG,aAAa,CAAC;IAClC,EAAE,EAAE,8BAA8B;IAClC,UAAU,EAAE,eAAe;IAC3B,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACxE,QAAQ,EAAE,CAAC,WAAW,CAAC;CACvB,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/agent-codex",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Codex integration for Effect applications",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/agent-codex#readme",
6
6
  "bugs": {
@@ -16,7 +16,7 @@
16
16
  "type": "module",
17
17
  "imports": {
18
18
  "#*.ts": {
19
- "source": "./src/*.ts",
19
+ "@shivaedev/source": "./src/*.ts",
20
20
  "types": "./dist/*.d.ts",
21
21
  "default": "./dist/*.js"
22
22
  },
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "exports": {
26
26
  "./*.ts": {
27
- "source": "./src/*.ts",
27
+ "@shivaedev/source": "./src/*.ts",
28
28
  "types": "./dist/*.d.ts",
29
29
  "default": "./dist/*.js"
30
30
  },
@@ -40,13 +40,13 @@
40
40
  "README.md"
41
41
  ],
42
42
  "dependencies": {
43
- "@shivaedev/agent": "0.2.0",
44
- "@shivaedev/service": "0.6.2"
43
+ "@shivaedev/agent": "0.3.0",
44
+ "@shivaedev/service": "0.7.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@effect/vitest": "4.0.6",
48
- "@shivaedev/quality": "0.58.0",
49
- "@shivaedev/test-story": "0.37.0",
48
+ "@shivaedev/quality": "0.60.0",
49
+ "@shivaedev/test-story": "0.38.0",
50
50
  "@types/node": "24.19.2",
51
51
  "effect": "4.0.6",
52
52
  "typescript": "7.0.2",
@@ -0,0 +1,29 @@
1
+ import { Effect, PubSub, Stream } from "effect";
2
+ import type { ConfiguredBackend } from "@shivaedev/agent/backend.ts";
3
+ import type { RunEvent } from "@shivaedev/agent/events.ts";
4
+ import type { EngineState } from "#adapters/initializeEngine.ts";
5
+
6
+ export function backend(state: EngineState) {
7
+ const configured: ConfiguredBackend = {
8
+ backend: "codex",
9
+ events: (receipt) =>
10
+ Stream.unwrap(
11
+ Effect.gen(function* () {
12
+ const session = state.sessions.get(receipt.session?.value ?? "");
13
+ if (session === undefined) {
14
+ return Stream.empty;
15
+ }
16
+ const subscription = yield* PubSub.subscribe(session.events);
17
+ return Stream.fromIterable<RunEvent>([
18
+ { receipt, type: "acknowledged" },
19
+ { reference: session.threadId, type: "session.opened" },
20
+ ]).pipe(Stream.concat(Stream.fromSubscription(subscription)), Stream.interruptWhen(state.exited));
21
+ }),
22
+ ),
23
+ features: state.features,
24
+ inspect: state.inspect,
25
+ reconcile: state.reconcile,
26
+ start: state.start,
27
+ };
28
+ return Effect.fn("Codex.backend")(() => Effect.succeed(configured));
29
+ }
@@ -0,0 +1,17 @@
1
+ import { Effect } from "effect";
2
+ import type { EngineState } from "#adapters/initializeEngine.ts";
3
+ import { sweepSpawnedDescendants } from "#adapters/threadSweep.ts";
4
+
5
+ export function census(state: Pick<EngineState, "claims" | "read">) {
6
+ return Effect.fn("Codex.census")((rootThreadId: string) =>
7
+ sweepSpawnedDescendants(state.read, rootThreadId).pipe(
8
+ Effect.tap((children) =>
9
+ Effect.sync(() => {
10
+ for (const child of children) {
11
+ state.claims.claim(rootThreadId, child.threadId);
12
+ }
13
+ }),
14
+ ),
15
+ ),
16
+ );
17
+ }
@@ -0,0 +1,6 @@
1
+ import { Effect } from "effect";
2
+ import type { ConfiguredBackend } from "@shivaedev/agent/backend.ts";
3
+
4
+ export const configuredBackend = Effect.fn("Codex.configuredBackend")((codex: { readonly backend: () => Effect.Effect<ConfiguredBackend> }) =>
5
+ codex.backend(),
6
+ );
@@ -1,101 +1,11 @@
1
- import { Effect, PubSub, Semaphore, Stream } from "effect";
2
- import type { ConfiguredBackend } from "@shivaedev/agent/backend.ts";
3
- import type { RunEvent } from "@shivaedev/agent/events.ts";
4
- import { Rejected, UnknownAcceptance } from "@shivaedev/agent/failures.ts";
5
- import type { ImageInput, StartRequest } from "@shivaedev/agent/run.ts";
6
- import { features } from "#adapters/features.ts";
1
+ import { Effect } from "effect";
2
+ import { backend } from "#adapters/backend.ts";
3
+ import { census } from "#adapters/census.ts";
4
+ import { initializeEngine } from "#adapters/initializeEngine.ts";
7
5
  import type { LineProcess } from "#adapters/process.ts";
8
- import { observe, readRequest } from "#adapters/reads.ts";
9
- import { receiptOf, recovery } from "#adapters/recovery.ts";
10
- import { AppServer, openServer } from "#adapters/server.ts";
11
- import { openSession, type Session } from "#adapters/session.ts";
12
- import { sweepSpawnedDescendants } from "#adapters/threadSweep.ts";
13
6
  import type { CodexConfiguration } from "#config.ts";
7
+
14
8
  export const engine = Effect.fn("Codex.engine")(function* (config: CodexConfiguration, spawn?: () => LineProcess) {
15
- const server = yield* openServer(config, spawn);
16
- const sessions = new Map<string, Session>();
17
- const { operations, refusals, reconcile } = yield* recovery(sessions).pipe(Effect.provideService(AppServer, server));
18
- const submissionGate = yield* Semaphore.make(1);
19
- const submit = Effect.fn("Codex.submit")(function* (
20
- request: Omit<StartRequest, "input"> & { readonly input: ImageInput },
21
- reference?: { value: string; version: number },
22
- ) {
23
- if (operations.has(request.operationId)) {
24
- const result = yield* reconcile(request.operationId);
25
- if (result.type === "accepted") {
26
- return result.receipt;
27
- }
28
- if (result.type === "not-accepted") {
29
- return yield* new Rejected({ backend: "codex", message: result.evidence });
30
- }
31
- return yield* new UnknownAcceptance({
32
- backend: "codex",
33
- message: result.reason,
34
- operationId: request.operationId,
35
- });
36
- }
37
- if (reference !== undefined && (reference.version !== 1 || server.claims.isNode(reference.value))) {
38
- return yield* new Rejected({ backend: "codex", message: "Child threads are observed passively and cannot be resumed" });
39
- }
40
- operations.set(request.operationId, reference?.value);
41
- const session = yield* openSession(config, request, reference?.value, (operationId, threadId) => {
42
- operations.set(operationId, threadId);
43
- }).pipe(Effect.provideService(AppServer, server));
44
- operations.set(request.operationId, session.threadId);
45
- sessions.set(session.threadId, session);
46
- yield* Effect.addFinalizer(() =>
47
- Effect.sync(() => {
48
- if (sessions.get(session.threadId) === session) {
49
- sessions.delete(session.threadId);
50
- }
51
- }),
52
- );
53
- const turnId = yield* session.driver.start(request.input, request.operationId);
54
- return receiptOf(request.operationId, session.threadId, turnId);
55
- });
56
- function start(request: Omit<StartRequest, "input"> & { readonly input: ImageInput }, session?: { value: string; version: number }) {
57
- return Semaphore.withPermit(submissionGate)(submit(request, session)).pipe(
58
- Effect.tapError((error) =>
59
- Effect.sync(() => {
60
- if (error._tag === "Rejected") {
61
- refusals.set(request.operationId, error.message);
62
- }
63
- }),
64
- ),
65
- );
66
- }
67
- const backend: ConfiguredBackend = {
68
- backend: "codex",
69
- events: (receipt) =>
70
- Stream.unwrap(
71
- Effect.gen(function* () {
72
- const session = sessions.get(receipt.session?.value ?? "");
73
- if (session === undefined) {
74
- return Stream.empty;
75
- }
76
- const subscription = yield* PubSub.subscribe(session.events);
77
- return Stream.fromIterable<RunEvent>([
78
- { receipt, type: "acknowledged" },
79
- { reference: session.threadId, type: "session.opened" },
80
- ]).pipe(Stream.concat(Stream.fromSubscription(subscription)), Stream.interruptWhen(server.exited));
81
- }),
82
- ),
83
- features: yield* features(sessions, start).pipe(Effect.provideService(AppServer, server)),
84
- inspect: (receipt) => observe(receipt).pipe(Effect.provideService(AppServer, server)),
85
- reconcile,
86
- start,
87
- };
88
- return {
89
- backend: () => Effect.succeed(backend),
90
- census: (rootThreadId: string) =>
91
- sweepSpawnedDescendants((method, params) => readRequest(method, params).pipe(Effect.provideService(AppServer, server)), rootThreadId).pipe(
92
- Effect.tap((children) =>
93
- Effect.sync(() => {
94
- for (const child of children) {
95
- server.claims.claim(rootThreadId, child.threadId);
96
- }
97
- }),
98
- ),
99
- ),
100
- };
9
+ const state = yield* initializeEngine(config, spawn);
10
+ return { backend: backend(state), census: census(state) };
101
11
  });
@@ -0,0 +1,8 @@
1
+ import { Effect } from "effect";
2
+ import { initializeEngine } from "#adapters/initializeEngine.ts";
3
+ import { CodexConfig } from "#config.ts";
4
+
5
+ export const initializeCodex = Effect.gen(function* () {
6
+ const config = yield* CodexConfig;
7
+ return yield* initializeEngine(config);
8
+ });
@@ -0,0 +1,75 @@
1
+ import { Effect, Semaphore } from "effect";
2
+ import { Rejected, UnknownAcceptance } from "@shivaedev/agent/failures.ts";
3
+ import type { ImageInput, Receipt, StartRequest } from "@shivaedev/agent/run.ts";
4
+ import { features } from "#adapters/features.ts";
5
+ import type { LineProcess } from "#adapters/process.ts";
6
+ import { observe, readRequest } from "#adapters/reads.ts";
7
+ import { receiptOf, recovery } from "#adapters/recovery.ts";
8
+ import { AppServer, openServer } from "#adapters/server.ts";
9
+ import { openSession, type Session } from "#adapters/session.ts";
10
+ import type { CodexConfiguration } from "#config.ts";
11
+ export const initializeEngine = Effect.fn("Codex.initializeEngine")(function* (config: CodexConfiguration, spawn?: () => LineProcess) {
12
+ const server = yield* openServer(config, spawn);
13
+ const sessions = new Map<string, Session>();
14
+ const { operations, refusals, reconcile } = yield* recovery(sessions).pipe(Effect.provideService(AppServer, server));
15
+ const submissionGate = yield* Semaphore.make(1);
16
+ const submit = Effect.fn("Codex.submit")(function* (
17
+ request: Omit<StartRequest, "input"> & { readonly input: ImageInput },
18
+ reference?: { value: string; version: number },
19
+ ) {
20
+ if (operations.has(request.operationId)) {
21
+ const result = yield* reconcile(request.operationId);
22
+ if (result.type === "accepted") {
23
+ return result.receipt;
24
+ }
25
+ if (result.type === "not-accepted") {
26
+ return yield* new Rejected({ backend: "codex", message: result.evidence });
27
+ }
28
+ return yield* new UnknownAcceptance({
29
+ backend: "codex",
30
+ message: result.reason,
31
+ operationId: request.operationId,
32
+ });
33
+ }
34
+ if (reference !== undefined && (reference.version !== 1 || server.claims.isNode(reference.value))) {
35
+ return yield* new Rejected({ backend: "codex", message: "Child threads are observed passively and cannot be resumed" });
36
+ }
37
+ operations.set(request.operationId, reference?.value);
38
+ const session = yield* openSession(config, request, reference?.value, (operationId, threadId) => {
39
+ operations.set(operationId, threadId);
40
+ }).pipe(Effect.provideService(AppServer, server));
41
+ operations.set(request.operationId, session.threadId);
42
+ sessions.set(session.threadId, session);
43
+ yield* Effect.addFinalizer(() =>
44
+ Effect.sync(() => {
45
+ if (sessions.get(session.threadId) === session) {
46
+ sessions.delete(session.threadId);
47
+ }
48
+ }),
49
+ );
50
+ const turnId = yield* session.driver.start(request.input, request.operationId);
51
+ return receiptOf(request.operationId, session.threadId, turnId);
52
+ });
53
+ function start(request: Omit<StartRequest, "input"> & { readonly input: ImageInput }, session?: { value: string; version: number }) {
54
+ return Semaphore.withPermit(submissionGate)(submit(request, session)).pipe(
55
+ Effect.tapError((error) =>
56
+ Effect.sync(() => {
57
+ if (error._tag === "Rejected") {
58
+ refusals.set(request.operationId, error.message);
59
+ }
60
+ }),
61
+ ),
62
+ );
63
+ }
64
+ return {
65
+ claims: server.claims,
66
+ exited: server.exited,
67
+ features: yield* features(sessions, start).pipe(Effect.provideService(AppServer, server)),
68
+ inspect: (receipt: Receipt) => observe(receipt).pipe(Effect.provideService(AppServer, server)),
69
+ read: (method: string, params: unknown) => readRequest(method, params).pipe(Effect.provideService(AppServer, server)),
70
+ reconcile,
71
+ sessions,
72
+ start,
73
+ };
74
+ });
75
+ export type EngineState = Effect.Success<ReturnType<typeof initializeEngine>>;
package/src/codex.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { Effect, Layer } from "effect";
2
2
  import { Backend } from "@shivaedev/agent/backend.ts";
3
3
  import { defineService } from "@shivaedev/service/defineService.ts";
4
- import { engine } from "#adapters/engine.ts";
4
+ import { backend } from "#adapters/backend.ts";
5
+ import { census } from "#adapters/census.ts";
6
+ import { configuredBackend } from "#adapters/configuredBackend.ts";
7
+ import { initializeCodex } from "#adapters/initializeCodex.ts";
5
8
  import { CodexConfig } from "#config.ts";
6
9
  export const Codex = defineService({
7
10
  id: "@shivaedev/agent-codex/Codex",
8
- initialize: Effect.gen(function* () {
9
- const config = yield* CodexConfig;
10
- return yield* engine(config);
11
- }),
12
- methods: (state) => state,
11
+ initialize: initializeCodex,
12
+ methods: (state) => ({ backend: backend(state), census: census(state) }),
13
13
  requires: [CodexConfig],
14
14
  });
15
- export const codexLayer = Layer.effect(Backend)(Effect.flatMap(Codex, (codex) => codex.backend())).pipe(Layer.provideMerge(Codex.layer));
15
+ export const codexLayer = Layer.effect(Backend)(Effect.flatMap(Codex, configuredBackend)).pipe(Layer.provideMerge(Codex.layer));