octto 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.
- package/README.md +28 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/loader.d.ts +3 -1
- package/dist/config/schema.d.ts +3 -0
- package/dist/hooks/fragment-injector.d.ts +37 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.js +182 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -117,6 +117,34 @@ Optional `~/.config/opencode/octto.json`:
|
|
|
117
117
|
|--------|------|---------|-------------|
|
|
118
118
|
| `port` | number | `0` (random) | Fixed port for the browser UI server |
|
|
119
119
|
| `agents` | object | - | Override agent models/settings |
|
|
120
|
+
| `fragments` | object | - | Custom instructions injected into agent prompts |
|
|
121
|
+
|
|
122
|
+
### Fragments
|
|
123
|
+
|
|
124
|
+
Inject custom instructions into agent prompts. Useful for customizing agent behavior per-project or globally.
|
|
125
|
+
|
|
126
|
+
**Global config** (`~/.config/opencode/octto.json`):
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"fragments": {
|
|
131
|
+
"octto": ["Always suggest 3 implementation approaches"],
|
|
132
|
+
"probe": ["Include emoji in every question"],
|
|
133
|
+
"bootstrapper": ["Focus on technical feasibility"]
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Project config** (`.octto/fragments.json` in your project root):
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"octto": ["This project uses React - focus on component patterns"],
|
|
143
|
+
"probe": ["Ask about testing strategy for each feature"]
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Fragments are merged: global fragments load first, project fragments append. Each fragment becomes a bullet point in a `<user-instructions>` block prepended to the agent's system prompt.
|
|
120
148
|
|
|
121
149
|
### Environment Variables
|
|
122
150
|
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { AgentOverride, CustomConfig, OcttoConfig } from "./loader";
|
|
1
|
+
export type { AgentOverride, CustomConfig, Fragments, OcttoConfig } from "./loader";
|
|
2
2
|
export { loadCustomConfig, resolvePort } from "./loader";
|
|
3
|
-
export { AgentOverrideSchema, OcttoConfigSchema, PortSchema } from "./schema";
|
|
3
|
+
export { AgentOverrideSchema, FragmentsSchema, OcttoConfigSchema, PortSchema } from "./schema";
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentConfig } from "@opencode-ai/sdk";
|
|
2
2
|
import { AGENTS } from "@/agents";
|
|
3
|
-
|
|
3
|
+
import { type Fragments } from "./schema";
|
|
4
|
+
export type { AgentOverride, Fragments, OcttoConfig } from "./schema";
|
|
4
5
|
/**
|
|
5
6
|
* Resolve port from environment variable or config.
|
|
6
7
|
* Priority: OCTTO_PORT env var > config port > default (0 = random)
|
|
@@ -9,6 +10,7 @@ export declare function resolvePort(configPort?: number): number;
|
|
|
9
10
|
export interface CustomConfig {
|
|
10
11
|
agents: Record<AGENTS, AgentConfig>;
|
|
11
12
|
port: number;
|
|
13
|
+
fragments: Fragments;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Load user configuration and merge with plugin agents.
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ export declare const AgentOverrideSchema: Omit<v.ObjectSchema<{
|
|
|
39
39
|
} | undefined;
|
|
40
40
|
};
|
|
41
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>]>;
|
|
42
|
+
export declare const FragmentsSchema: v.OptionalSchema<v.RecordSchema<v.EnumSchema<typeof AGENTS, undefined>, v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, undefined>;
|
|
42
43
|
export declare const OcttoConfigSchema: v.ObjectSchema<{
|
|
43
44
|
readonly agents: v.OptionalSchema<v.RecordSchema<v.EnumSchema<typeof AGENTS, undefined>, Omit<v.ObjectSchema<{
|
|
44
45
|
readonly model: v.StringSchema<undefined>;
|
|
@@ -79,6 +80,8 @@ export declare const OcttoConfigSchema: v.ObjectSchema<{
|
|
|
79
80
|
} | undefined;
|
|
80
81
|
}, undefined>, undefined>;
|
|
81
82
|
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>;
|
|
83
|
+
readonly fragments: v.OptionalSchema<v.RecordSchema<v.EnumSchema<typeof AGENTS, undefined>, v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, undefined>;
|
|
82
84
|
}, undefined>;
|
|
83
85
|
export type AgentOverride = v.InferOutput<typeof AgentOverrideSchema>;
|
|
86
|
+
export type Fragments = v.InferOutput<typeof FragmentsSchema>;
|
|
84
87
|
export type OcttoConfig = v.InferOutput<typeof OcttoConfigSchema>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
type FragmentsRecord = Record<string, string[]> | undefined;
|
|
2
|
+
/**
|
|
3
|
+
* Format fragments array as an XML block to prepend to agent prompts.
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatFragmentsBlock(fragments: string[] | undefined): string;
|
|
6
|
+
/**
|
|
7
|
+
* Merge global and project fragments.
|
|
8
|
+
* Global fragments come first, project fragments append.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mergeFragments(global: FragmentsRecord, project: FragmentsRecord): Record<string, string[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Load project-level fragments from .octto/fragments.json
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadProjectFragments(projectDir: string): Promise<Record<string, string[]> | undefined>;
|
|
15
|
+
/**
|
|
16
|
+
* Calculate Levenshtein distance between two strings.
|
|
17
|
+
* Used for suggesting similar agent names for typos.
|
|
18
|
+
*/
|
|
19
|
+
export declare function levenshteinDistance(a: string, b: string): number;
|
|
20
|
+
/**
|
|
21
|
+
* Warn about unknown agent names in fragments config.
|
|
22
|
+
* Suggests similar valid agent names for likely typos.
|
|
23
|
+
*/
|
|
24
|
+
export declare function warnUnknownAgents(fragments: Record<string, string[]> | undefined): void;
|
|
25
|
+
export interface FragmentInjectorContext {
|
|
26
|
+
projectDir: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a fragment injector that can modify agent system prompts.
|
|
30
|
+
* Returns merged fragments from global config and project config.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createFragmentInjector(ctx: FragmentInjectorContext, globalFragments: FragmentsRecord): Promise<Record<string, string[]>>;
|
|
33
|
+
/**
|
|
34
|
+
* Get the system prompt prefix for a specific agent.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getAgentSystemPromptPrefix(fragments: Record<string, string[]>, agentName: string): string;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createFragmentInjector, type FragmentInjectorContext, formatFragmentsBlock, getAgentSystemPromptPrefix, levenshteinDistance, loadProjectFragments, mergeFragments, warnUnknownAgents, } from "./fragment-injector";
|
package/dist/index.js
CHANGED
|
@@ -509,6 +509,58 @@ function getFallback(schema, dataset, config$1) {
|
|
|
509
509
|
function getDefault(schema, dataset, config$1) {
|
|
510
510
|
return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
|
|
511
511
|
}
|
|
512
|
+
function array(item, message$1) {
|
|
513
|
+
return {
|
|
514
|
+
kind: "schema",
|
|
515
|
+
type: "array",
|
|
516
|
+
reference: array,
|
|
517
|
+
expects: "Array",
|
|
518
|
+
async: false,
|
|
519
|
+
item,
|
|
520
|
+
message: message$1,
|
|
521
|
+
get "~standard"() {
|
|
522
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
523
|
+
},
|
|
524
|
+
"~run"(dataset, config$1) {
|
|
525
|
+
const input = dataset.value;
|
|
526
|
+
if (Array.isArray(input)) {
|
|
527
|
+
dataset.typed = true;
|
|
528
|
+
dataset.value = [];
|
|
529
|
+
for (let key = 0;key < input.length; key++) {
|
|
530
|
+
const value$1 = input[key];
|
|
531
|
+
const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
|
|
532
|
+
if (itemDataset.issues) {
|
|
533
|
+
const pathItem = {
|
|
534
|
+
type: "array",
|
|
535
|
+
origin: "value",
|
|
536
|
+
input,
|
|
537
|
+
key,
|
|
538
|
+
value: value$1
|
|
539
|
+
};
|
|
540
|
+
for (const issue of itemDataset.issues) {
|
|
541
|
+
if (issue.path)
|
|
542
|
+
issue.path.unshift(pathItem);
|
|
543
|
+
else
|
|
544
|
+
issue.path = [pathItem];
|
|
545
|
+
dataset.issues?.push(issue);
|
|
546
|
+
}
|
|
547
|
+
if (!dataset.issues)
|
|
548
|
+
dataset.issues = itemDataset.issues;
|
|
549
|
+
if (config$1.abortEarly) {
|
|
550
|
+
dataset.typed = false;
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (!itemDataset.typed)
|
|
555
|
+
dataset.typed = false;
|
|
556
|
+
dataset.value.push(itemDataset.value);
|
|
557
|
+
}
|
|
558
|
+
} else
|
|
559
|
+
_addIssue(this, "type", dataset, config$1);
|
|
560
|
+
return dataset;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
}
|
|
512
564
|
function enum_(enum__, message$1) {
|
|
513
565
|
const options = [];
|
|
514
566
|
for (const key in enum__)
|
|
@@ -796,9 +848,11 @@ var AgentOverrideSchema = partial(object({
|
|
|
796
848
|
maxSteps: pipe(number(), integer(), minValue(1))
|
|
797
849
|
}));
|
|
798
850
|
var PortSchema = pipe(number(), integer(), minValue(0), maxValue(65535));
|
|
851
|
+
var FragmentsSchema = optional(record(enum_(AGENTS), array(string())));
|
|
799
852
|
var OcttoConfigSchema = object({
|
|
800
853
|
agents: optional(record(enum_(AGENTS), AgentOverrideSchema)),
|
|
801
|
-
port: optional(PortSchema)
|
|
854
|
+
port: optional(PortSchema),
|
|
855
|
+
fragments: FragmentsSchema
|
|
802
856
|
});
|
|
803
857
|
|
|
804
858
|
// src/config/loader.ts
|
|
@@ -880,9 +934,117 @@ async function loadCustomConfig(agents2, configDir) {
|
|
|
880
934
|
}
|
|
881
935
|
return {
|
|
882
936
|
agents: mergedAgents,
|
|
883
|
-
port: resolvePort(config?.port)
|
|
937
|
+
port: resolvePort(config?.port),
|
|
938
|
+
fragments: config?.fragments
|
|
884
939
|
};
|
|
885
940
|
}
|
|
941
|
+
// src/hooks/fragment-injector.ts
|
|
942
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
943
|
+
import { join as join2 } from "path";
|
|
944
|
+
var VALID_AGENT_NAMES2 = Object.values(AGENTS);
|
|
945
|
+
var ProjectFragmentsSchema = record(string(), array(string()));
|
|
946
|
+
function formatFragmentsBlock(fragments) {
|
|
947
|
+
if (!fragments || fragments.length === 0) {
|
|
948
|
+
return "";
|
|
949
|
+
}
|
|
950
|
+
const bulletPoints = fragments.map((f) => `- ${f}`).join(`
|
|
951
|
+
`);
|
|
952
|
+
return `<user-instructions>
|
|
953
|
+
${bulletPoints}
|
|
954
|
+
</user-instructions>
|
|
955
|
+
|
|
956
|
+
`;
|
|
957
|
+
}
|
|
958
|
+
function mergeFragments(global, project) {
|
|
959
|
+
const result = {};
|
|
960
|
+
if (global) {
|
|
961
|
+
for (const [agent4, frags] of Object.entries(global)) {
|
|
962
|
+
result[agent4] = [...frags];
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
if (project) {
|
|
966
|
+
for (const [agent4, frags] of Object.entries(project)) {
|
|
967
|
+
if (result[agent4]) {
|
|
968
|
+
result[agent4].push(...frags);
|
|
969
|
+
} else {
|
|
970
|
+
result[agent4] = [...frags];
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return result;
|
|
975
|
+
}
|
|
976
|
+
async function loadProjectFragments(projectDir) {
|
|
977
|
+
const fragmentsPath = join2(projectDir, ".octto", "fragments.json");
|
|
978
|
+
try {
|
|
979
|
+
const content = await readFile2(fragmentsPath, "utf-8");
|
|
980
|
+
const parsed = JSON.parse(content);
|
|
981
|
+
const result = safeParse(ProjectFragmentsSchema, parsed);
|
|
982
|
+
if (!result.success) {
|
|
983
|
+
console.warn(`[octto] Invalid fragments.json schema in ${fragmentsPath}`);
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
return result.output;
|
|
987
|
+
} catch {
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
function levenshteinDistance(a, b) {
|
|
992
|
+
if (a.length === 0)
|
|
993
|
+
return b.length;
|
|
994
|
+
if (b.length === 0)
|
|
995
|
+
return a.length;
|
|
996
|
+
const matrix = [];
|
|
997
|
+
for (let i = 0;i <= b.length; i++) {
|
|
998
|
+
matrix[i] = [i];
|
|
999
|
+
}
|
|
1000
|
+
for (let j = 0;j <= a.length; j++) {
|
|
1001
|
+
matrix[0][j] = j;
|
|
1002
|
+
}
|
|
1003
|
+
for (let i = 1;i <= b.length; i++) {
|
|
1004
|
+
for (let j = 1;j <= a.length; j++) {
|
|
1005
|
+
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
1006
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
1007
|
+
} else {
|
|
1008
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
return matrix[b.length][a.length];
|
|
1013
|
+
}
|
|
1014
|
+
function warnUnknownAgents(fragments) {
|
|
1015
|
+
if (!fragments)
|
|
1016
|
+
return;
|
|
1017
|
+
for (const agentName of Object.keys(fragments)) {
|
|
1018
|
+
if (VALID_AGENT_NAMES2.includes(agentName)) {
|
|
1019
|
+
continue;
|
|
1020
|
+
}
|
|
1021
|
+
let closest;
|
|
1022
|
+
let minDistance = Infinity;
|
|
1023
|
+
for (const validName of VALID_AGENT_NAMES2) {
|
|
1024
|
+
const distance = levenshteinDistance(agentName, validName);
|
|
1025
|
+
if (distance < minDistance && distance <= 3) {
|
|
1026
|
+
minDistance = distance;
|
|
1027
|
+
closest = validName;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
let message = `[octto] Unknown agent "${agentName}" in fragments config.`;
|
|
1031
|
+
if (closest) {
|
|
1032
|
+
message += ` Did you mean "${closest}"?`;
|
|
1033
|
+
}
|
|
1034
|
+
message += ` Valid agents: ${VALID_AGENT_NAMES2.join(", ")}`;
|
|
1035
|
+
console.warn(message);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
async function createFragmentInjector(ctx, globalFragments) {
|
|
1039
|
+
const projectFragments = await loadProjectFragments(ctx.projectDir);
|
|
1040
|
+
const merged = mergeFragments(globalFragments, projectFragments);
|
|
1041
|
+
warnUnknownAgents(globalFragments);
|
|
1042
|
+
warnUnknownAgents(projectFragments);
|
|
1043
|
+
return merged;
|
|
1044
|
+
}
|
|
1045
|
+
function getAgentSystemPromptPrefix(fragments, agentName) {
|
|
1046
|
+
return formatFragmentsBlock(fragments[agentName]);
|
|
1047
|
+
}
|
|
886
1048
|
// src/constants.ts
|
|
887
1049
|
var DEFAULT_ANSWER_TIMEOUT_MS = 300000;
|
|
888
1050
|
|
|
@@ -3101,7 +3263,7 @@ __export(exports_external, {
|
|
|
3101
3263
|
bigint: () => bigint2,
|
|
3102
3264
|
base64url: () => base64url2,
|
|
3103
3265
|
base64: () => base642,
|
|
3104
|
-
array: () =>
|
|
3266
|
+
array: () => array2,
|
|
3105
3267
|
any: () => any,
|
|
3106
3268
|
_function: () => _function,
|
|
3107
3269
|
_default: () => _default2,
|
|
@@ -3597,8 +3759,8 @@ function getEnumValues(entries) {
|
|
|
3597
3759
|
const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
|
|
3598
3760
|
return values;
|
|
3599
3761
|
}
|
|
3600
|
-
function joinValues(
|
|
3601
|
-
return
|
|
3762
|
+
function joinValues(array2, separator = "|") {
|
|
3763
|
+
return array2.map((val) => stringifyPrimitive(val)).join(separator);
|
|
3602
3764
|
}
|
|
3603
3765
|
function jsonStringifyReplacer(_, value) {
|
|
3604
3766
|
if (typeof value === "bigint")
|
|
@@ -14286,7 +14448,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
14286
14448
|
inst.nullable = () => nullable(inst);
|
|
14287
14449
|
inst.nullish = () => optional2(nullable(inst));
|
|
14288
14450
|
inst.nonoptional = (params) => nonoptional(inst, params);
|
|
14289
|
-
inst.array = () =>
|
|
14451
|
+
inst.array = () => array2(inst);
|
|
14290
14452
|
inst.or = (arg) => union([inst, arg]);
|
|
14291
14453
|
inst.and = (arg) => intersection(inst, arg);
|
|
14292
14454
|
inst.transform = (tx) => pipe2(inst, transform(tx));
|
|
@@ -14707,7 +14869,7 @@ var ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
|
14707
14869
|
inst.length = (len, params) => inst.check(_length(len, params));
|
|
14708
14870
|
inst.unwrap = () => inst.element;
|
|
14709
14871
|
});
|
|
14710
|
-
function
|
|
14872
|
+
function array2(element, params) {
|
|
14711
14873
|
return _array(ZodArray, element, params);
|
|
14712
14874
|
}
|
|
14713
14875
|
function keyof(schema) {
|
|
@@ -15169,7 +15331,7 @@ var ZodFunction = /* @__PURE__ */ $constructor("ZodFunction", (inst, def) => {
|
|
|
15169
15331
|
function _function(params) {
|
|
15170
15332
|
return new ZodFunction({
|
|
15171
15333
|
type: "function",
|
|
15172
|
-
input: Array.isArray(params?.input) ? tuple(params?.input) : params?.input ??
|
|
15334
|
+
input: Array.isArray(params?.input) ? tuple(params?.input) : params?.input ?? array2(unknown()),
|
|
15173
15335
|
output: params?.output ?? unknown()
|
|
15174
15336
|
});
|
|
15175
15337
|
}
|
|
@@ -15213,7 +15375,7 @@ var stringbool = (...args) => _stringbool({
|
|
|
15213
15375
|
}, ...args);
|
|
15214
15376
|
function json(params) {
|
|
15215
15377
|
const jsonSchema = lazy(() => {
|
|
15216
|
-
return union([string3(params), number3(), boolean2(), _null3(),
|
|
15378
|
+
return union([string3(params), number3(), boolean2(), _null3(), array2(jsonSchema), record2(string3(), jsonSchema)]);
|
|
15217
15379
|
});
|
|
15218
15380
|
return jsonSchema;
|
|
15219
15381
|
}
|
|
@@ -15279,7 +15441,7 @@ tool.schema = exports_external;
|
|
|
15279
15441
|
|
|
15280
15442
|
// src/state/persistence.ts
|
|
15281
15443
|
import { existsSync, mkdirSync, readdirSync, rmSync } from "fs";
|
|
15282
|
-
import { join as
|
|
15444
|
+
import { join as join3 } from "path";
|
|
15283
15445
|
function validateSessionId(sessionId) {
|
|
15284
15446
|
if (!/^[a-zA-Z0-9_-]+$/.test(sessionId)) {
|
|
15285
15447
|
throw new Error(`Invalid session ID: ${sessionId}`);
|
|
@@ -15288,7 +15450,7 @@ function validateSessionId(sessionId) {
|
|
|
15288
15450
|
function createStatePersistence(baseDir = ".brainstorm") {
|
|
15289
15451
|
function getFilePath(sessionId) {
|
|
15290
15452
|
validateSessionId(sessionId);
|
|
15291
|
-
return
|
|
15453
|
+
return join3(baseDir, `${sessionId}.json`);
|
|
15292
15454
|
}
|
|
15293
15455
|
function ensureDir() {
|
|
15294
15456
|
if (!existsSync(baseDir)) {
|
|
@@ -16539,8 +16701,16 @@ function createOcttoTools(sessions, client) {
|
|
|
16539
16701
|
}
|
|
16540
16702
|
|
|
16541
16703
|
// src/index.ts
|
|
16542
|
-
var Octto = async ({ client }) => {
|
|
16704
|
+
var Octto = async ({ client, directory }) => {
|
|
16543
16705
|
const customConfig = await loadCustomConfig(agents);
|
|
16706
|
+
const fragments = await createFragmentInjector({ projectDir: directory }, customConfig.fragments);
|
|
16707
|
+
for (const agentName of Object.values(AGENTS)) {
|
|
16708
|
+
const prefix = getAgentSystemPromptPrefix(fragments, agentName);
|
|
16709
|
+
if (prefix && customConfig.agents[agentName]?.prompt) {
|
|
16710
|
+
customConfig.agents[agentName].prompt = prefix + customConfig.agents[agentName].prompt;
|
|
16711
|
+
}
|
|
16712
|
+
}
|
|
16713
|
+
warnUnknownAgents(customConfig.fragments);
|
|
16544
16714
|
const sessions = createSessionStore({ port: customConfig.port });
|
|
16545
16715
|
const tracked = new Map;
|
|
16546
16716
|
const tools = createOcttoTools(sessions, client);
|