octto 0.1.4 → 0.2.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.
- package/README.md +20 -0
- package/dist/config/index.d.ts +3 -3
- package/dist/config/loader.d.ts +11 -2
- package/dist/config/schema.d.ts +2 -0
- package/dist/index.js +29 -13
- package/dist/session/server.d.ts +1 -1
- package/dist/session/sessions.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,12 +104,32 @@ Optional `~/.config/opencode/octto.json`:
|
|
|
104
104
|
|
|
105
105
|
```json
|
|
106
106
|
{
|
|
107
|
+
"port": 3000,
|
|
107
108
|
"agents": {
|
|
108
109
|
"probe": { "model": "anthropic/claude-sonnet-4" }
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
```
|
|
112
113
|
|
|
114
|
+
### Options
|
|
115
|
+
|
|
116
|
+
| Option | Type | Default | Description |
|
|
117
|
+
|--------|------|---------|-------------|
|
|
118
|
+
| `port` | number | `0` (random) | Fixed port for the browser UI server |
|
|
119
|
+
| `agents` | object | - | Override agent models/settings |
|
|
120
|
+
|
|
121
|
+
### Environment Variables
|
|
122
|
+
|
|
123
|
+
| Variable | Description |
|
|
124
|
+
|----------|-------------|
|
|
125
|
+
| `OCTTO_PORT` | Override port (takes precedence over config file) |
|
|
126
|
+
|
|
127
|
+
For Docker workflows, set a fixed port:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
OCTTO_PORT=3000 opencode
|
|
131
|
+
```
|
|
132
|
+
|
|
113
133
|
## Development
|
|
114
134
|
|
|
115
135
|
```bash
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
3
|
-
export { AgentOverrideSchema, OcttoConfigSchema } from "./schema";
|
|
1
|
+
export type { AgentOverride, CustomConfig, OcttoConfig } from "./loader";
|
|
2
|
+
export { loadCustomConfig, resolvePort } from "./loader";
|
|
3
|
+
export { AgentOverrideSchema, OcttoConfigSchema, PortSchema } from "./schema";
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import type { AgentConfig } from "@opencode-ai/sdk";
|
|
2
2
|
import { AGENTS } from "@/agents";
|
|
3
3
|
export type { AgentOverride, OcttoConfig } from "./schema";
|
|
4
|
+
/**
|
|
5
|
+
* Resolve port from environment variable or config.
|
|
6
|
+
* Priority: OCTTO_PORT env var > config port > default (0 = random)
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolvePort(configPort?: number): number;
|
|
9
|
+
export interface CustomConfig {
|
|
10
|
+
agents: Record<AGENTS, AgentConfig>;
|
|
11
|
+
port: number;
|
|
12
|
+
}
|
|
4
13
|
/**
|
|
5
14
|
* Load user configuration and merge with plugin agents.
|
|
6
|
-
* Returns merged agent configs with user overrides applied.
|
|
15
|
+
* Returns merged agent configs with user overrides applied, and resolved port.
|
|
7
16
|
*/
|
|
8
|
-
export declare function loadCustomConfig(agents: Record<AGENTS, AgentConfig>, configDir?: string): Promise<
|
|
17
|
+
export declare function loadCustomConfig(agents: Record<AGENTS, AgentConfig>, configDir?: string): Promise<CustomConfig>;
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare const AgentOverrideSchema: Omit<v.ObjectSchema<{
|
|
|
38
38
|
readonly issue: v.ObjectIssue | v.StringIssue | v.NumberIssue | v.MinValueIssue<number, 0> | v.MaxValueIssue<number, 2> | v.IntegerIssue<number> | v.MinValueIssue<number, 1>;
|
|
39
39
|
} | undefined;
|
|
40
40
|
};
|
|
41
|
+
export declare const PortSchema: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 65535, undefined>]>;
|
|
41
42
|
export declare const OcttoConfigSchema: v.ObjectSchema<{
|
|
42
43
|
readonly agents: v.OptionalSchema<v.RecordSchema<v.EnumSchema<typeof AGENTS, undefined>, Omit<v.ObjectSchema<{
|
|
43
44
|
readonly model: v.StringSchema<undefined>;
|
|
@@ -77,6 +78,7 @@ export declare const OcttoConfigSchema: v.ObjectSchema<{
|
|
|
77
78
|
readonly issue: v.ObjectIssue | v.StringIssue | v.NumberIssue | v.MinValueIssue<number, 0> | v.MaxValueIssue<number, 2> | v.IntegerIssue<number> | v.MinValueIssue<number, 1>;
|
|
78
79
|
} | undefined;
|
|
79
80
|
}, undefined>, undefined>;
|
|
81
|
+
readonly port: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 65535, undefined>]>, undefined>;
|
|
80
82
|
}, undefined>;
|
|
81
83
|
export type AgentOverride = v.InferOutput<typeof AgentOverrideSchema>;
|
|
82
84
|
export type OcttoConfig = v.InferOutput<typeof OcttoConfigSchema>;
|
package/dist/index.js
CHANGED
|
@@ -795,11 +795,25 @@ var AgentOverrideSchema = partial(object({
|
|
|
795
795
|
temperature: pipe(number(), minValue(0), maxValue(2)),
|
|
796
796
|
maxSteps: pipe(number(), integer(), minValue(1))
|
|
797
797
|
}));
|
|
798
|
+
var PortSchema = pipe(number(), integer(), minValue(0), maxValue(65535));
|
|
798
799
|
var OcttoConfigSchema = object({
|
|
799
|
-
agents: optional(record(enum_(AGENTS), AgentOverrideSchema))
|
|
800
|
+
agents: optional(record(enum_(AGENTS), AgentOverrideSchema)),
|
|
801
|
+
port: optional(PortSchema)
|
|
800
802
|
});
|
|
801
803
|
|
|
802
804
|
// src/config/loader.ts
|
|
805
|
+
var OCTTO_PORT_ENV = "OCTTO_PORT";
|
|
806
|
+
var DEFAULT_PORT = 0;
|
|
807
|
+
function resolvePort(configPort) {
|
|
808
|
+
const envValue = process.env[OCTTO_PORT_ENV];
|
|
809
|
+
if (envValue !== undefined) {
|
|
810
|
+
const parsed = Number(envValue);
|
|
811
|
+
if (Number.isInteger(parsed) && parsed >= 0 && parsed <= 65535) {
|
|
812
|
+
return parsed;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
return configPort ?? DEFAULT_PORT;
|
|
816
|
+
}
|
|
803
817
|
var VALID_AGENT_NAMES = Object.values(AGENTS);
|
|
804
818
|
function formatValidationErrors(issues) {
|
|
805
819
|
return issues.map((issue) => {
|
|
@@ -858,14 +872,16 @@ async function load(configDir) {
|
|
|
858
872
|
}
|
|
859
873
|
async function loadCustomConfig(agents2, configDir) {
|
|
860
874
|
const config = await load(configDir);
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
result[name] = { ...agents2[name], ...override };
|
|
875
|
+
const mergedAgents = { ...agents2 };
|
|
876
|
+
if (config?.agents) {
|
|
877
|
+
for (const [name, override] of Object.entries(config.agents)) {
|
|
878
|
+
mergedAgents[name] = { ...agents2[name], ...override };
|
|
879
|
+
}
|
|
867
880
|
}
|
|
868
|
-
return
|
|
881
|
+
return {
|
|
882
|
+
agents: mergedAgents,
|
|
883
|
+
port: resolvePort(config?.port)
|
|
884
|
+
};
|
|
869
885
|
}
|
|
870
886
|
// src/constants.ts
|
|
871
887
|
var DEFAULT_ANSWER_TIMEOUT_MS = 300000;
|
|
@@ -2504,10 +2520,10 @@ function getHtmlBundle() {
|
|
|
2504
2520
|
</html>`;
|
|
2505
2521
|
}
|
|
2506
2522
|
// src/session/server.ts
|
|
2507
|
-
async function createServer(sessionId, store) {
|
|
2523
|
+
async function createServer(sessionId, store, configuredPort) {
|
|
2508
2524
|
const htmlBundle = getHtmlBundle();
|
|
2509
2525
|
const server = Bun.serve({
|
|
2510
|
-
port: 0,
|
|
2526
|
+
port: configuredPort ?? 0,
|
|
2511
2527
|
fetch(req, server2) {
|
|
2512
2528
|
const url = new URL(req.url);
|
|
2513
2529
|
if (url.pathname === "/ws") {
|
|
@@ -2665,7 +2681,7 @@ function createSessionStore(options = {}) {
|
|
|
2665
2681
|
const store = {
|
|
2666
2682
|
async startSession(input) {
|
|
2667
2683
|
const sessionId = generateSessionId();
|
|
2668
|
-
const { server, port } = await createServer(sessionId, store);
|
|
2684
|
+
const { server, port } = await createServer(sessionId, store, options.port);
|
|
2669
2685
|
const url = `http://localhost:${port}`;
|
|
2670
2686
|
const session = {
|
|
2671
2687
|
id: sessionId,
|
|
@@ -16525,7 +16541,7 @@ function createOcttoTools(sessions, client) {
|
|
|
16525
16541
|
// src/index.ts
|
|
16526
16542
|
var Octto = async ({ client }) => {
|
|
16527
16543
|
const customConfig = await loadCustomConfig(agents);
|
|
16528
|
-
const sessions = createSessionStore();
|
|
16544
|
+
const sessions = createSessionStore({ port: customConfig.port });
|
|
16529
16545
|
const tracked = new Map;
|
|
16530
16546
|
const tools = createOcttoTools(sessions, client);
|
|
16531
16547
|
const originalExecute = tools.start_session.execute;
|
|
@@ -16543,7 +16559,7 @@ var Octto = async ({ client }) => {
|
|
|
16543
16559
|
return {
|
|
16544
16560
|
tool: tools,
|
|
16545
16561
|
config: async (config2) => {
|
|
16546
|
-
config2.agent = { ...config2.agent, ...customConfig };
|
|
16562
|
+
config2.agent = { ...config2.agent, ...customConfig.agents };
|
|
16547
16563
|
},
|
|
16548
16564
|
event: async ({ event }) => {
|
|
16549
16565
|
if (event.type !== "session.deleted")
|
package/dist/session/server.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { SessionStore } from "./sessions";
|
|
|
3
3
|
interface WsData {
|
|
4
4
|
sessionId: string;
|
|
5
5
|
}
|
|
6
|
-
export declare function createServer(sessionId: string, store: SessionStore): Promise<{
|
|
6
|
+
export declare function createServer(sessionId: string, store: SessionStore, configuredPort?: number): Promise<{
|
|
7
7
|
server: Server<WsData>;
|
|
8
8
|
port: number;
|
|
9
9
|
}>;
|
|
@@ -3,6 +3,8 @@ import { type BaseConfig, type EndSessionOutput, type GetAnswerInput, type GetAn
|
|
|
3
3
|
export interface SessionStoreOptions {
|
|
4
4
|
/** Skip opening browser - useful for tests */
|
|
5
5
|
skipBrowser?: boolean;
|
|
6
|
+
/** Fixed port for the server (0 = random available port) */
|
|
7
|
+
port?: number;
|
|
6
8
|
}
|
|
7
9
|
export interface SessionStore {
|
|
8
10
|
startSession: (input: StartSessionInput) => Promise<StartSessionOutput>;
|