@shivaedev/agent-codex 0.2.0 → 0.3.1
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/CHANGELOG.md +12 -0
- package/dist/adapters/backend.d.ts +5 -0
- package/dist/adapters/backend.d.ts.map +1 -0
- package/dist/adapters/backend.js +23 -0
- package/dist/adapters/backend.js.map +1 -0
- package/dist/adapters/census.d.ts +4 -0
- package/dist/adapters/census.d.ts.map +1 -0
- package/dist/adapters/census.js +10 -0
- package/dist/adapters/census.js.map +1 -0
- package/dist/adapters/configuredBackend.d.ts +6 -0
- package/dist/adapters/configuredBackend.d.ts.map +1 -0
- package/dist/adapters/configuredBackend.js +3 -0
- package/dist/adapters/configuredBackend.js.map +1 -0
- package/dist/adapters/engine.d.ts +3 -5
- package/dist/adapters/engine.d.ts.map +1 -1
- package/dist/adapters/engine.js +6 -77
- package/dist/adapters/engine.js.map +1 -1
- package/dist/adapters/initializeCodex.d.ts +770 -0
- package/dist/adapters/initializeCodex.d.ts.map +1 -0
- package/dist/adapters/initializeCodex.js +8 -0
- package/dist/adapters/initializeCodex.js.map +1 -0
- package/dist/adapters/initializeEngine.d.ts +774 -0
- package/dist/adapters/initializeEngine.d.ts.map +1 -0
- package/dist/adapters/initializeEngine.js +63 -0
- package/dist/adapters/initializeEngine.js.map +1 -0
- package/dist/codex.d.ts +2 -2
- package/dist/codex.d.ts.map +1 -1
- package/dist/codex.js +7 -7
- package/dist/codex.js.map +1 -1
- package/package.json +10 -10
- package/src/adapters/backend.ts +29 -0
- package/src/adapters/census.ts +17 -0
- package/src/adapters/configuredBackend.ts +6 -0
- package/src/adapters/engine.ts +7 -97
- package/src/adapters/initializeCodex.ts +8 -0
- package/src/adapters/initializeEngine.ts +75 -0
- 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
|
};
|
package/dist/codex.d.ts.map
CHANGED
|
@@ -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;
|
|
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 {
|
|
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:
|
|
9
|
-
|
|
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,
|
|
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,
|
|
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.
|
|
3
|
+
"version": "0.3.1",
|
|
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,20 +40,20 @@
|
|
|
40
40
|
"README.md"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@shivaedev/agent": "0.
|
|
44
|
-
"@shivaedev/service": "0.
|
|
43
|
+
"@shivaedev/agent": "0.3.1",
|
|
44
|
+
"@shivaedev/service": "0.7.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@effect/vitest": "4.0.
|
|
48
|
-
"@shivaedev/quality": "0.
|
|
49
|
-
"@shivaedev/test-story": "0.
|
|
47
|
+
"@effect/vitest": "4.0.7",
|
|
48
|
+
"@shivaedev/quality": "0.61.1",
|
|
49
|
+
"@shivaedev/test-story": "0.39.1",
|
|
50
50
|
"@types/node": "24.19.2",
|
|
51
|
-
"effect": "4.0.
|
|
51
|
+
"effect": "4.0.7",
|
|
52
52
|
"typescript": "7.0.2",
|
|
53
53
|
"vitest": "5.0.5"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"effect": "4.0.
|
|
56
|
+
"effect": "4.0.7"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">=24"
|
|
@@ -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
|
+
);
|
package/src/adapters/engine.ts
CHANGED
|
@@ -1,101 +1,11 @@
|
|
|
1
|
-
import { Effect
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
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
|
|
16
|
-
|
|
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 {
|
|
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:
|
|
9
|
-
|
|
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,
|
|
15
|
+
export const codexLayer = Layer.effect(Backend)(Effect.flatMap(Codex, configuredBackend)).pipe(Layer.provideMerge(Codex.layer));
|