@frenchtoastman/oh-my-groundcontrol 0.0.20 → 0.0.22
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/dist/cli/index.js +4 -3
- package/dist/config/schema.d.ts +7 -5
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/langfuse-body/index.d.ts +39 -0
- package/dist/hooks/langfuse-common.d.ts +15 -0
- package/dist/hooks/langfuse-tracing/index.d.ts +39 -0
- package/dist/index.js +48 -30
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -13772,9 +13772,10 @@ var HashlineEditConfigSchema = exports_external.object({
|
|
|
13772
13772
|
var DoubleConfirmationConfigSchema = exports_external.object({
|
|
13773
13773
|
enabled: exports_external.boolean().default(false)
|
|
13774
13774
|
});
|
|
13775
|
-
var
|
|
13775
|
+
var LangfuseTracingConfigSchema = exports_external.object({
|
|
13776
13776
|
enabled: exports_external.boolean().default(false),
|
|
13777
|
-
|
|
13777
|
+
traceUserId: exports_external.string().default("opencode"),
|
|
13778
|
+
customMetadata: exports_external.record(exports_external.string(), exports_external.unknown()).default({})
|
|
13778
13779
|
});
|
|
13779
13780
|
var PluginConfigSchema = exports_external.object({
|
|
13780
13781
|
preset: exports_external.string().optional(),
|
|
@@ -13791,7 +13792,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
13791
13792
|
sessionExport: SessionExportConfigSchema.optional(),
|
|
13792
13793
|
hashline_edit: HashlineEditConfigSchema.optional(),
|
|
13793
13794
|
double_confirmation: DoubleConfirmationConfigSchema.optional(),
|
|
13794
|
-
|
|
13795
|
+
langfuse_tracing: LangfuseTracingConfigSchema.optional()
|
|
13795
13796
|
});
|
|
13796
13797
|
// src/config/agent-mcps.ts
|
|
13797
13798
|
var DEFAULT_AGENT_MCPS = {
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -165,11 +165,12 @@ export declare const DoubleConfirmationConfigSchema: z.ZodObject<{
|
|
|
165
165
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
166
166
|
}, z.core.$strip>;
|
|
167
167
|
export type DoubleConfirmationConfig = z.infer<typeof DoubleConfirmationConfigSchema>;
|
|
168
|
-
export declare const
|
|
168
|
+
export declare const LangfuseTracingConfigSchema: z.ZodObject<{
|
|
169
169
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
170
|
-
|
|
170
|
+
traceUserId: z.ZodDefault<z.ZodString>;
|
|
171
|
+
customMetadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
171
172
|
}, z.core.$strip>;
|
|
172
|
-
export type
|
|
173
|
+
export type LangfuseTracingConfig = z.infer<typeof LangfuseTracingConfigSchema>;
|
|
173
174
|
export declare const PluginConfigSchema: z.ZodObject<{
|
|
174
175
|
preset: z.ZodOptional<z.ZodString>;
|
|
175
176
|
scoringEngineVersion: z.ZodOptional<z.ZodEnum<{
|
|
@@ -303,9 +304,10 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
303
304
|
double_confirmation: z.ZodOptional<z.ZodObject<{
|
|
304
305
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
305
306
|
}, z.core.$strip>>;
|
|
306
|
-
|
|
307
|
+
langfuse_tracing: z.ZodOptional<z.ZodObject<{
|
|
307
308
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
308
|
-
|
|
309
|
+
traceUserId: z.ZodDefault<z.ZodString>;
|
|
310
|
+
customMetadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
309
311
|
}, z.core.$strip>>;
|
|
310
312
|
}, z.core.$strip>;
|
|
311
313
|
export type PluginConfig = z.infer<typeof PluginConfigSchema>;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { createDoubleConfirmationHook } from './double-confirmation';
|
|
|
6
6
|
export { createEditErrorRecoveryHook } from './edit-error-recovery';
|
|
7
7
|
export { createHashlineReadEnhancerHook } from './hashline-read-enhancer';
|
|
8
8
|
export { createJsonErrorRecoveryHook } from './json-error-recovery';
|
|
9
|
-
export {
|
|
9
|
+
export { createLangfuseTracingHook } from './langfuse-tracing';
|
|
10
10
|
export { createPhaseReminderHook } from './phase-reminder';
|
|
11
11
|
export { createPostReadNudgeHook } from './post-read-nudge';
|
|
12
12
|
export { createQuestionRouterHook } from './question-router';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { LangfuseBodyConfig } from '../../config/schema';
|
|
2
|
+
interface ChatParamsInput {
|
|
3
|
+
sessionID: string;
|
|
4
|
+
agent: string;
|
|
5
|
+
model: {
|
|
6
|
+
id: string;
|
|
7
|
+
providerID: string;
|
|
8
|
+
};
|
|
9
|
+
provider: {
|
|
10
|
+
source: string;
|
|
11
|
+
info: unknown;
|
|
12
|
+
options: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
message: unknown;
|
|
15
|
+
}
|
|
16
|
+
interface ChatParamsOutput {
|
|
17
|
+
temperature?: number;
|
|
18
|
+
topP?: number;
|
|
19
|
+
topK?: number;
|
|
20
|
+
options: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates the Langfuse body injection hook.
|
|
24
|
+
*
|
|
25
|
+
* Injects metadata into the LLM request body via `chat.params`
|
|
26
|
+
* → `output.options.metadata`, which flows through the Vercel AI
|
|
27
|
+
* SDK's `providerOptions` into the HTTP request body.
|
|
28
|
+
*
|
|
29
|
+
* LiteLLM proxy reads body-level `metadata` and forwards recognised
|
|
30
|
+
* keys (tags, session_id, trace_user_id, trace_name,
|
|
31
|
+
* generation_name) to Langfuse for trace enrichment.
|
|
32
|
+
*
|
|
33
|
+
* Ships disabled by default — enable via
|
|
34
|
+
* config.langfuse_body.enabled.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createLangfuseBodyHook(config?: Partial<LangfuseBodyConfig>): {
|
|
37
|
+
'chat.params': (input: ChatParamsInput, output: ChatParamsOutput) => Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Langfuse utilities for agent-to-task mapping and tag derivation.
|
|
3
|
+
*/
|
|
4
|
+
export declare const AGENT_TASK_MAP: Record<string, string>;
|
|
5
|
+
/**
|
|
6
|
+
* Derive the task type for an agent.
|
|
7
|
+
* Returns undefined for empty agent.
|
|
8
|
+
* Falls back to 'general' for unknown agents.
|
|
9
|
+
*/
|
|
10
|
+
export declare function deriveTask(agent: string): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Derive Langfuse tags for an agent.
|
|
13
|
+
* Returns ['opencode', agentName, taskType], filtering out empty values.
|
|
14
|
+
*/
|
|
15
|
+
export declare function deriveTags(agent: string): string[];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { LangfuseTracingConfig } from '../../config/schema';
|
|
2
|
+
interface ChatParamsInput {
|
|
3
|
+
sessionID: string;
|
|
4
|
+
agent: string;
|
|
5
|
+
model: {
|
|
6
|
+
id: string;
|
|
7
|
+
providerID: string;
|
|
8
|
+
};
|
|
9
|
+
provider: {
|
|
10
|
+
source: string;
|
|
11
|
+
info: unknown;
|
|
12
|
+
options: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
message: unknown;
|
|
15
|
+
}
|
|
16
|
+
interface ChatParamsOutput {
|
|
17
|
+
temperature?: number;
|
|
18
|
+
topP?: number;
|
|
19
|
+
topK?: number;
|
|
20
|
+
options: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates the Langfuse tracing hook.
|
|
24
|
+
*
|
|
25
|
+
* Injects metadata into the LLM request body via `chat.params`
|
|
26
|
+
* → `output.options.metadata`, which flows through the Vercel AI
|
|
27
|
+
* SDK's `providerOptions` into the HTTP request body.
|
|
28
|
+
*
|
|
29
|
+
* LiteLLM proxy reads body-level `metadata` and forwards recognised
|
|
30
|
+
* keys (tags, session_id, trace_user_id, trace_name,
|
|
31
|
+
* generation_name) to Langfuse for trace enrichment.
|
|
32
|
+
*
|
|
33
|
+
* Ships disabled by default — enable via
|
|
34
|
+
* config.langfuse_tracing.enabled.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createLangfuseTracingHook(config?: Partial<LangfuseTracingConfig>): {
|
|
37
|
+
'chat.params': (input: ChatParamsInput, output: ChatParamsOutput) => Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -17104,9 +17104,10 @@ var HashlineEditConfigSchema = exports_external.object({
|
|
|
17104
17104
|
var DoubleConfirmationConfigSchema = exports_external.object({
|
|
17105
17105
|
enabled: exports_external.boolean().default(false)
|
|
17106
17106
|
});
|
|
17107
|
-
var
|
|
17107
|
+
var LangfuseTracingConfigSchema = exports_external.object({
|
|
17108
17108
|
enabled: exports_external.boolean().default(false),
|
|
17109
|
-
|
|
17109
|
+
traceUserId: exports_external.string().default("opencode"),
|
|
17110
|
+
customMetadata: exports_external.record(exports_external.string(), exports_external.unknown()).default({})
|
|
17110
17111
|
});
|
|
17111
17112
|
var PluginConfigSchema = exports_external.object({
|
|
17112
17113
|
preset: exports_external.string().optional(),
|
|
@@ -17123,7 +17124,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
17123
17124
|
sessionExport: SessionExportConfigSchema.optional(),
|
|
17124
17125
|
hashline_edit: HashlineEditConfigSchema.optional(),
|
|
17125
17126
|
double_confirmation: DoubleConfirmationConfigSchema.optional(),
|
|
17126
|
-
|
|
17127
|
+
langfuse_tracing: LangfuseTracingConfigSchema.optional()
|
|
17127
17128
|
});
|
|
17128
17129
|
|
|
17129
17130
|
// src/config/loader.ts
|
|
@@ -23149,7 +23150,7 @@ ${JSON_ERROR_REMINDER}`;
|
|
|
23149
23150
|
}
|
|
23150
23151
|
};
|
|
23151
23152
|
}
|
|
23152
|
-
// src/hooks/langfuse-
|
|
23153
|
+
// src/hooks/langfuse-common.ts
|
|
23153
23154
|
var AGENT_TASK_MAP = {
|
|
23154
23155
|
orchestrator: "planning",
|
|
23155
23156
|
explorer: "research",
|
|
@@ -23157,46 +23158,63 @@ var AGENT_TASK_MAP = {
|
|
|
23157
23158
|
designer: "design",
|
|
23158
23159
|
librarian: "research",
|
|
23159
23160
|
oracle: "analysis",
|
|
23160
|
-
build: "coding",
|
|
23161
23161
|
verification: "verification",
|
|
23162
23162
|
"pre-flight": "planning",
|
|
23163
23163
|
contractor: "planning",
|
|
23164
|
-
groundcontrol: "planning"
|
|
23165
|
-
"power-slap-red": "coding",
|
|
23166
|
-
"power-slap-blue": "coding",
|
|
23167
|
-
"power-slap-green": "coding"
|
|
23164
|
+
groundcontrol: "planning"
|
|
23168
23165
|
};
|
|
23169
|
-
function
|
|
23166
|
+
function deriveTask(agent) {
|
|
23167
|
+
if (!agent)
|
|
23168
|
+
return;
|
|
23169
|
+
return AGENT_TASK_MAP[agent] ?? "general";
|
|
23170
|
+
}
|
|
23171
|
+
function deriveTags(agent) {
|
|
23172
|
+
const tags = [];
|
|
23173
|
+
if (agent)
|
|
23174
|
+
tags.push(`agent:${agent}`);
|
|
23175
|
+
const task = deriveTask(agent);
|
|
23176
|
+
if (task)
|
|
23177
|
+
tags.push(`task:${task}`);
|
|
23178
|
+
return tags;
|
|
23179
|
+
}
|
|
23180
|
+
|
|
23181
|
+
// src/hooks/langfuse-tracing/index.ts
|
|
23182
|
+
function createLangfuseTracingHook(config2) {
|
|
23170
23183
|
const enabled = config2?.enabled ?? false;
|
|
23171
|
-
const
|
|
23184
|
+
const traceUserId = config2?.traceUserId ?? "opencode";
|
|
23185
|
+
const customMetadata = config2?.customMetadata ?? {};
|
|
23172
23186
|
const pluginVersion = getCachedVersion() ?? "unknown";
|
|
23173
23187
|
return {
|
|
23174
|
-
"chat.
|
|
23188
|
+
"chat.params": async (input, output) => {
|
|
23175
23189
|
if (!enabled)
|
|
23176
23190
|
return;
|
|
23177
23191
|
try {
|
|
23178
|
-
const
|
|
23179
|
-
|
|
23180
|
-
|
|
23181
|
-
|
|
23182
|
-
|
|
23183
|
-
|
|
23184
|
-
|
|
23185
|
-
|
|
23186
|
-
|
|
23192
|
+
const tags = deriveTags(input.agent);
|
|
23193
|
+
const task = deriveTask(input.agent);
|
|
23194
|
+
const metadata = {
|
|
23195
|
+
...output.options.metadata ?? {},
|
|
23196
|
+
tags,
|
|
23197
|
+
session_id: input.sessionID || undefined,
|
|
23198
|
+
trace_user_id: traceUserId || undefined,
|
|
23199
|
+
trace_name: input.agent || undefined,
|
|
23200
|
+
generation_name: task || undefined,
|
|
23201
|
+
model: input.model?.id || undefined,
|
|
23202
|
+
provider: input.model?.providerID || undefined,
|
|
23203
|
+
plugin_version: pluginVersion || undefined
|
|
23187
23204
|
};
|
|
23188
|
-
for (const [key, value] of Object.entries(
|
|
23189
|
-
if (value) {
|
|
23190
|
-
|
|
23205
|
+
for (const [key, value] of Object.entries(customMetadata)) {
|
|
23206
|
+
if (value !== undefined && value !== null) {
|
|
23207
|
+
metadata[key] = value;
|
|
23191
23208
|
}
|
|
23192
23209
|
}
|
|
23193
|
-
for (const
|
|
23194
|
-
if (
|
|
23195
|
-
|
|
23210
|
+
for (const key of Object.keys(metadata)) {
|
|
23211
|
+
if (metadata[key] === undefined) {
|
|
23212
|
+
delete metadata[key];
|
|
23196
23213
|
}
|
|
23197
23214
|
}
|
|
23215
|
+
output.options.metadata = metadata;
|
|
23198
23216
|
} catch (err) {
|
|
23199
|
-
log("[langfuse-
|
|
23217
|
+
log("[langfuse-tracing] Error injecting metadata:", err);
|
|
23200
23218
|
}
|
|
23201
23219
|
}
|
|
23202
23220
|
};
|
|
@@ -39416,7 +39434,7 @@ var OhMyGroundControl = async (ctx) => {
|
|
|
39416
39434
|
const hashlineReadEnhancerHook = createHashlineReadEnhancerHook(config3.hashline_edit);
|
|
39417
39435
|
const editErrorRecoveryHook = createEditErrorRecoveryHook();
|
|
39418
39436
|
const doubleConfirmationHook = createDoubleConfirmationHook(config3.double_confirmation);
|
|
39419
|
-
const
|
|
39437
|
+
const langfuseTracingHook = createLangfuseTracingHook(config3.langfuse_tracing);
|
|
39420
39438
|
const hashlineEditEnabled = config3.hashline_edit?.enabled !== false;
|
|
39421
39439
|
const hashlineEditTool = hashlineEditEnabled ? createHashlineEditTool() : undefined;
|
|
39422
39440
|
return {
|
|
@@ -39521,7 +39539,7 @@ var OhMyGroundControl = async (ctx) => {
|
|
|
39521
39539
|
"experimental.chat.messages.transform": phaseReminderHook["experimental.chat.messages.transform"],
|
|
39522
39540
|
"chat.message": questionRouterHook["chat.message"],
|
|
39523
39541
|
"command.execute.before": analyzeCommandHook["command.execute.before"],
|
|
39524
|
-
"chat.
|
|
39542
|
+
"chat.params": langfuseTracingHook["chat.params"],
|
|
39525
39543
|
"tool.execute.after": async (input, output) => {
|
|
39526
39544
|
await delegateTaskRetryHook["tool.execute.after"](input, output);
|
|
39527
39545
|
await jsonErrorRecoveryHook["tool.execute.after"](input, output);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frenchtoastman/oh-my-groundcontrol",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"description": "An OpenCode plugin for multi-agent orchestration for structured planning with NASA-style guardrails.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|