@coffer-org/plugin-claude-agent 2.1.0 → 2.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/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { definePlugin } from '@coffer-org/sdk/plugin';
2
2
  import { defineSettings } from '@coffer-org/sdk/settings';
3
3
  import { field } from '@coffer-org/sdk/fields';
4
+ import { MODEL_PROFILES } from "./models.js";
4
5
  export default definePlugin({
5
6
  id: 'claude-agent',
6
7
  version: '1.0.0',
@@ -8,31 +9,54 @@ export default definePlugin({
8
9
  settings: defineSettings({
9
10
  label: 'claude-agent.settings.label',
10
11
  fields: [
11
- field.select({
12
- key: 'auth_mode',
13
- label: 'claude-agent.settings.auth_mode',
14
- default: 'subscription',
15
- options: [
16
- { value: 'subscription', title: 'claude-agent.settings.auth_mode_subscription' },
17
- { value: 'api_key', title: 'claude-agent.settings.auth_mode_api_key' },
12
+ field.group({
13
+ label: 'claude-agent.settings.groups.runtime',
14
+ icon: 'lucide:bot',
15
+ fields: [
16
+ field.select({
17
+ key: 'auth_mode',
18
+ label: 'claude-agent.settings.auth_mode',
19
+ default: 'subscription',
20
+ options: [
21
+ { value: 'subscription', title: 'claude-agent.settings.auth_mode_subscription' },
22
+ { value: 'api_key', title: 'claude-agent.settings.auth_mode_api_key' },
23
+ ],
24
+ }),
25
+ field.password({
26
+ key: 'anthropic_api_key',
27
+ label: 'claude-agent.settings.anthropic_api_key',
28
+ view: { hidden: { auth_mode: { $ne: 'api_key' } } },
29
+ }),
30
+ field.select({
31
+ key: 'claude_model',
32
+ label: 'claude-agent.settings.claude_model',
33
+ default: 'haiku',
34
+ options: MODEL_PROFILES.map((p) => ({ value: p.value, title: p.title })),
35
+ }),
36
+ field.boolean({ key: 'thinking_enabled', label: 'claude-agent.settings.thinking_enabled', default: false }),
37
+ field.boolean({ key: 'skip_permissions', label: 'claude-agent.settings.skip_permissions', default: true }),
38
+ field.int({ key: 'response_timeout', label: 'claude-agent.settings.response_timeout', default: 600 }),
18
39
  ],
19
40
  }),
20
- field.password({
21
- key: 'anthropic_api_key',
22
- label: 'claude-agent.settings.anthropic_api_key',
23
- view: { hidden: { auth_mode: { $ne: 'api_key' } } },
41
+ field.group({
42
+ label: 'claude-agent.settings.groups.rag',
43
+ icon: 'lucide:search',
44
+ fields: [
45
+ field.boolean({ key: 'rag_enabled', label: 'claude-agent.settings.rag_enabled', default: true }),
46
+ field.password({ key: 'openai_api_key', label: 'claude-agent.settings.openai_api_key' }),
47
+ field.int({ key: 'rag_top_k', label: 'claude-agent.settings.rag_top_k', default: 5, view: { hidden: true } }),
48
+ ],
49
+ }),
50
+ field.group({
51
+ label: 'claude-agent.settings.groups.langfuse',
52
+ icon: 'lucide:activity',
53
+ fields: [
54
+ field.boolean({ key: 'tracing_enabled', label: 'claude-agent.settings.tracing_enabled' }),
55
+ field.string({ key: 'langfuse_base_url', label: 'claude-agent.settings.langfuse_base_url' }),
56
+ field.password({ key: 'langfuse_public_key', label: 'claude-agent.settings.langfuse_public_key' }),
57
+ field.password({ key: 'langfuse_secret_key', label: 'claude-agent.settings.langfuse_secret_key' }),
58
+ ],
24
59
  }),
25
- field.string({ key: 'claude_model', label: 'claude-agent.settings.claude_model', default: 'haiku' }),
26
- field.boolean({ key: 'skip_permissions', label: 'claude-agent.settings.skip_permissions', default: true }),
27
- field.int({ key: 'response_timeout', label: 'claude-agent.settings.response_timeout', default: 600 }),
28
- field.boolean({ key: 'rag_enabled', label: 'claude-agent.settings.rag_enabled', default: true }),
29
- field.int({ key: 'rag_top_k', label: 'claude-agent.settings.rag_top_k', default: 5 }),
30
- field.boolean({ key: 'thinking_enabled', label: 'claude-agent.settings.thinking_enabled', default: false }),
31
- field.password({ key: 'openai_api_key', label: 'claude-agent.settings.openai_api_key' }),
32
- field.password({ key: 'langfuse_public_key', label: 'claude-agent.settings.langfuse_public_key' }),
33
- field.password({ key: 'langfuse_secret_key', label: 'claude-agent.settings.langfuse_secret_key' }),
34
- field.string({ key: 'langfuse_base_url', label: 'claude-agent.settings.langfuse_base_url' }),
35
- field.boolean({ key: 'tracing_enabled', label: 'claude-agent.settings.tracing_enabled' }),
36
60
  ],
37
61
  }),
38
62
  });
@@ -0,0 +1,10 @@
1
+ export declare const EFFORT_LEVELS: readonly ["low", "medium", "high", "xhigh", "max"];
2
+ export type Effort = (typeof EFFORT_LEVELS)[number];
3
+ export interface ModelProfile {
4
+ value: string;
5
+ id: string;
6
+ effort: Effort | '';
7
+ title: string;
8
+ }
9
+ export declare const MODEL_PROFILES: ModelProfile[];
10
+ export declare function profileFor(value: string): ModelProfile;
package/dist/models.js ADDED
@@ -0,0 +1,24 @@
1
+ export const EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'];
2
+ export const MODEL_PROFILES = [
3
+ { value: 'haiku', id: 'claude-haiku-4-5', effort: '', title: 'Haiku 4.5 — найшвидша й найдешевша' },
4
+ { value: 'sonnet-low', id: 'claude-sonnet-5', effort: 'low', title: 'Sonnet 5 · швидко' },
5
+ { value: 'sonnet', id: 'claude-sonnet-5', effort: 'high', title: 'Sonnet 5 · ретельно' },
6
+ { value: 'opus', id: 'claude-opus-4-8', effort: 'high', title: 'Opus 4.8 · ретельно' },
7
+ { value: 'opus-5', id: 'claude-opus-5', effort: 'high', title: 'Opus 5 · ретельно' },
8
+ { value: 'opus-5-max', id: 'claude-opus-5', effort: 'max', title: 'Opus 5 · максимум' },
9
+ ];
10
+ const LEGACY_VALUES = {
11
+ 'claude-opus-5': 'opus-5',
12
+ 'claude-fable-5': 'opus-5-max',
13
+ 'claude-opus-4-8': 'opus',
14
+ 'claude-sonnet-5': 'sonnet',
15
+ 'claude-haiku-4-5': 'haiku',
16
+ };
17
+ export function profileFor(value) {
18
+ const direct = MODEL_PROFILES.find((p) => p.value === value);
19
+ if (direct)
20
+ return direct;
21
+ const legacy = LEGACY_VALUES[value];
22
+ const mapped = legacy ? MODEL_PROFILES.find((p) => p.value === legacy) : undefined;
23
+ return mapped ?? MODEL_PROFILES.find((p) => p.value === 'opus');
24
+ }
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import Anthropic from '@anthropic-ai/sdk';
3
- import { loadAgentConfig, modelId } from "./config.js";
3
+ import { effortParam, loadAgentConfig, modelId } from "./config.js";
4
4
  import { makeAgentTools } from "./coffer.js";
5
5
  import { buildDomainSections } from '@coffer-org/server/mcp-tools';
6
6
  import { isTracing, flushTracing, langfuseFactory, TurnTracer } from "./tracing.js";
@@ -155,6 +155,7 @@ export async function runAgent(request, deps = {}) {
155
155
  }
156
156
  }
157
157
  const thinking = thinkingParam(cfg.thinkingEnabled);
158
+ const outputConfig = effortParam(cfg.claudeModel);
158
159
  if (cfg.thinkingEnabled)
159
160
  log.info(`extended thinking ON (${modelId(cfg.claudeModel)})`);
160
161
  let tokensIn = null;
@@ -171,6 +172,7 @@ export async function runAgent(request, deps = {}) {
171
172
  messages,
172
173
  tools: tools,
173
174
  ...(thinking ? { thinking } : {}),
175
+ ...(outputConfig ? { output_config: outputConfig } : {}),
174
176
  }, { signal: ac.signal });
175
177
  stream.on('text', (delta) => {
176
178
  streamed = appendTextDelta(streamed, delta);
@@ -1,8 +1,15 @@
1
1
  export declare const APP_ROOT: string;
2
2
  export declare const PLUGIN_ROOT: string;
3
+ import { EFFORT_LEVELS, MODEL_PROFILES, profileFor, type Effort } from '../models.ts';
4
+ export { EFFORT_LEVELS, MODEL_PROFILES, profileFor };
5
+ export type { Effort };
3
6
  export type AuthMode = 'subscription' | 'api_key';
4
7
  export declare function supportsAdaptiveThinking(model: string): boolean;
5
- export declare function modelId(alias: string): string;
8
+ export declare function modelId(value: string): string;
9
+ export declare function supportsEffort(model: string): boolean;
10
+ export declare function effortParam(value: string): {
11
+ effort: Effort;
12
+ } | undefined;
6
13
  export interface AgentConfig {
7
14
  authMode: AuthMode;
8
15
  anthropicApiKey: string;
@@ -4,6 +4,8 @@ import { fileURLToPath } from 'node:url';
4
4
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
5
  export const APP_ROOT = path.resolve(__dirname, '../../../..');
6
6
  export const PLUGIN_ROOT = path.resolve(__dirname, '../..');
7
+ import { EFFORT_LEVELS, MODEL_PROFILES, profileFor } from "../models.js";
8
+ export { EFFORT_LEVELS, MODEL_PROFILES, profileFor };
7
9
  const ADAPTIVE_THINKING_MODELS = [
8
10
  'claude-opus-5', 'claude-opus-4-8', 'claude-opus-4-7', 'claude-opus-4-6',
9
11
  'claude-sonnet-5', 'claude-sonnet-4-6',
@@ -12,13 +14,15 @@ const ADAPTIVE_THINKING_MODELS = [
12
14
  export function supportsAdaptiveThinking(model) {
13
15
  return ADAPTIVE_THINKING_MODELS.some((m) => model === m || model.startsWith(`${m}-`));
14
16
  }
15
- export function modelId(alias) {
16
- const map = {
17
- haiku: 'claude-haiku-4-5',
18
- sonnet: 'claude-sonnet-5',
19
- opus: 'claude-opus-4-8',
20
- };
21
- return map[alias] ?? (alias.startsWith('claude-') ? alias : 'claude-opus-4-8');
17
+ export function modelId(value) {
18
+ return profileFor(value).id;
19
+ }
20
+ export function supportsEffort(model) {
21
+ return supportsAdaptiveThinking(model);
22
+ }
23
+ export function effortParam(value) {
24
+ const p = profileFor(value);
25
+ return p.effort && supportsEffort(p.id) ? { effort: p.effort } : undefined;
22
26
  }
23
27
  export function loadAgentConfig(opts = {}) {
24
28
  const env = opts.env ?? process.env;
@@ -32,7 +36,7 @@ export function loadAgentConfig(opts = {}) {
32
36
  skipPermissions: db.skip_permissions !== false,
33
37
  responseTimeout: Math.max(60, Number(env.AGENT_RESPONSE_TIMEOUT ?? db.response_timeout ?? 600) || 600),
34
38
  ragEnabled: db.rag_enabled !== false,
35
- ragTopK: Number(env.AGENT_RAG_TOP_K ?? db.rag_top_k ?? 5) || 5,
39
+ ragTopK: 5,
36
40
  thinkingEnabled: (env.AGENT_THINKING_ENABLED ?? String(db.thinking_enabled)) === 'true'
37
41
  && supportsAdaptiveThinking(modelId(claudeModel)),
38
42
  embeddingApiKey: env.OPENAI_API_KEY ?? db.openai_api_key ?? '',
package/dist/schema.js CHANGED
@@ -7084,72 +7084,132 @@ var src_default = definePlugin({
7084
7084
  settings: defineSettings({
7085
7085
  label: "claude-agent.settings.label",
7086
7086
  fields: [
7087
- field.select({
7088
- key: "auth_mode",
7089
- label: "claude-agent.settings.auth_mode",
7090
- default: "subscription",
7091
- options: [{
7092
- value: "subscription",
7093
- title: "claude-agent.settings.auth_mode_subscription"
7094
- }, {
7095
- value: "api_key",
7096
- title: "claude-agent.settings.auth_mode_api_key"
7097
- }]
7098
- }),
7099
- field.password({
7100
- key: "anthropic_api_key",
7101
- label: "claude-agent.settings.anthropic_api_key",
7102
- view: { hidden: { auth_mode: { $ne: "api_key" } } }
7103
- }),
7104
- field.string({
7105
- key: "claude_model",
7106
- label: "claude-agent.settings.claude_model",
7107
- default: "haiku"
7108
- }),
7109
- field.boolean({
7110
- key: "skip_permissions",
7111
- label: "claude-agent.settings.skip_permissions",
7112
- default: true
7113
- }),
7114
- field.int({
7115
- key: "response_timeout",
7116
- label: "claude-agent.settings.response_timeout",
7117
- default: 600
7118
- }),
7119
- field.boolean({
7120
- key: "rag_enabled",
7121
- label: "claude-agent.settings.rag_enabled",
7122
- default: true
7123
- }),
7124
- field.int({
7125
- key: "rag_top_k",
7126
- label: "claude-agent.settings.rag_top_k",
7127
- default: 5
7128
- }),
7129
- field.boolean({
7130
- key: "thinking_enabled",
7131
- label: "claude-agent.settings.thinking_enabled",
7132
- default: false
7133
- }),
7134
- field.password({
7135
- key: "openai_api_key",
7136
- label: "claude-agent.settings.openai_api_key"
7137
- }),
7138
- field.password({
7139
- key: "langfuse_public_key",
7140
- label: "claude-agent.settings.langfuse_public_key"
7141
- }),
7142
- field.password({
7143
- key: "langfuse_secret_key",
7144
- label: "claude-agent.settings.langfuse_secret_key"
7087
+ field.group({
7088
+ label: "claude-agent.settings.groups.runtime",
7089
+ icon: "lucide:bot",
7090
+ fields: [
7091
+ field.select({
7092
+ key: "auth_mode",
7093
+ label: "claude-agent.settings.auth_mode",
7094
+ default: "subscription",
7095
+ options: [{
7096
+ value: "subscription",
7097
+ title: "claude-agent.settings.auth_mode_subscription"
7098
+ }, {
7099
+ value: "api_key",
7100
+ title: "claude-agent.settings.auth_mode_api_key"
7101
+ }]
7102
+ }),
7103
+ field.password({
7104
+ key: "anthropic_api_key",
7105
+ label: "claude-agent.settings.anthropic_api_key",
7106
+ view: { hidden: { auth_mode: { $ne: "api_key" } } }
7107
+ }),
7108
+ field.select({
7109
+ key: "claude_model",
7110
+ label: "claude-agent.settings.claude_model",
7111
+ default: "haiku",
7112
+ options: [
7113
+ {
7114
+ value: "haiku",
7115
+ id: "claude-haiku-4-5",
7116
+ effort: "",
7117
+ title: "Haiku 4.5 — найшвидша й найдешевша"
7118
+ },
7119
+ {
7120
+ value: "sonnet-low",
7121
+ id: "claude-sonnet-5",
7122
+ effort: "low",
7123
+ title: "Sonnet 5 · швидко"
7124
+ },
7125
+ {
7126
+ value: "sonnet",
7127
+ id: "claude-sonnet-5",
7128
+ effort: "high",
7129
+ title: "Sonnet 5 · ретельно"
7130
+ },
7131
+ {
7132
+ value: "opus",
7133
+ id: "claude-opus-4-8",
7134
+ effort: "high",
7135
+ title: "Opus 4.8 · ретельно"
7136
+ },
7137
+ {
7138
+ value: "opus-5",
7139
+ id: "claude-opus-5",
7140
+ effort: "high",
7141
+ title: "Opus 5 · ретельно"
7142
+ },
7143
+ {
7144
+ value: "opus-5-max",
7145
+ id: "claude-opus-5",
7146
+ effort: "max",
7147
+ title: "Opus 5 · максимум"
7148
+ }
7149
+ ].map((p) => ({
7150
+ value: p.value,
7151
+ title: p.title
7152
+ }))
7153
+ }),
7154
+ field.boolean({
7155
+ key: "thinking_enabled",
7156
+ label: "claude-agent.settings.thinking_enabled",
7157
+ default: false
7158
+ }),
7159
+ field.boolean({
7160
+ key: "skip_permissions",
7161
+ label: "claude-agent.settings.skip_permissions",
7162
+ default: true
7163
+ }),
7164
+ field.int({
7165
+ key: "response_timeout",
7166
+ label: "claude-agent.settings.response_timeout",
7167
+ default: 600
7168
+ })
7169
+ ]
7145
7170
  }),
7146
- field.string({
7147
- key: "langfuse_base_url",
7148
- label: "claude-agent.settings.langfuse_base_url"
7171
+ field.group({
7172
+ label: "claude-agent.settings.groups.rag",
7173
+ icon: "lucide:search",
7174
+ fields: [
7175
+ field.boolean({
7176
+ key: "rag_enabled",
7177
+ label: "claude-agent.settings.rag_enabled",
7178
+ default: true
7179
+ }),
7180
+ field.password({
7181
+ key: "openai_api_key",
7182
+ label: "claude-agent.settings.openai_api_key"
7183
+ }),
7184
+ field.int({
7185
+ key: "rag_top_k",
7186
+ label: "claude-agent.settings.rag_top_k",
7187
+ default: 5,
7188
+ view: { hidden: true }
7189
+ })
7190
+ ]
7149
7191
  }),
7150
- field.boolean({
7151
- key: "tracing_enabled",
7152
- label: "claude-agent.settings.tracing_enabled"
7192
+ field.group({
7193
+ label: "claude-agent.settings.groups.langfuse",
7194
+ icon: "lucide:activity",
7195
+ fields: [
7196
+ field.boolean({
7197
+ key: "tracing_enabled",
7198
+ label: "claude-agent.settings.tracing_enabled"
7199
+ }),
7200
+ field.string({
7201
+ key: "langfuse_base_url",
7202
+ label: "claude-agent.settings.langfuse_base_url"
7203
+ }),
7204
+ field.password({
7205
+ key: "langfuse_public_key",
7206
+ label: "claude-agent.settings.langfuse_public_key"
7207
+ }),
7208
+ field.password({
7209
+ key: "langfuse_secret_key",
7210
+ label: "claude-agent.settings.langfuse_secret_key"
7211
+ })
7212
+ ]
7153
7213
  })
7154
7214
  ]
7155
7215
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffer-org/plugin-claude-agent",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24"
@@ -26,9 +26,9 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@anthropic-ai/sdk": "^0.111.0",
29
- "@coffer-org/mcp": "^2.1.0",
29
+ "@coffer-org/mcp": "^2.2.0",
30
30
  "@coffer-org/sdk": "^2.0.0",
31
- "@coffer-org/server": "^2.1.0",
31
+ "@coffer-org/server": "^2.1.1",
32
32
  "@langfuse/otel": "^4.6.1",
33
33
  "@langfuse/tracing": "^4.6.1",
34
34
  "@opentelemetry/sdk-trace-node": "^2.8.0",