@coffer-org/server 4.0.0 → 5.0.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.
@@ -1 +1 @@
1
- export declare function frontendInstructions(): Promise<string | null>;
1
+ export declare function frontendInstructions(siteUrl: string): Promise<string | null>;
@@ -10,9 +10,8 @@ import { readFile } from 'node:fs/promises';
10
10
  import { join } from 'node:path';
11
11
  import { pathToFileURL } from 'node:url';
12
12
  import { getLogger } from '@coffer-org/sdk/logger';
13
- import { configuredPublicUrl } from "./public-url.js";
14
13
  const log = getLogger('frontend-agent');
15
- export async function frontendInstructions() {
14
+ export async function frontendInstructions(siteUrl) {
16
15
  const dist = process.env['WEB_DIST'];
17
16
  if (!dist)
18
17
  return null;
@@ -27,7 +26,7 @@ export async function frontendInstructions() {
27
26
  log.warn(`frontend ${rel} exports no agent() — no site-link instructions`);
28
27
  return null;
29
28
  }
30
- const text = await mod.agent({ siteUrl: await configuredPublicUrl() });
29
+ const text = await mod.agent({ siteUrl });
31
30
  return typeof text === 'string' && text.trim() ? text : null;
32
31
  }
33
32
  catch (e) {
package/dist/mcp-http.js CHANGED
@@ -1,12 +1,14 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
- import { collectMcpTools, resolveRagDeps, buildDomainSections, buildMcpInstructions } from "./mcp-tools.js";
3
+ import { collectMcpTools, resolveRagDeps, buildDomainSections, buildMcpInstructions, siteSection, } from "./mcp-tools.js";
4
+ import { configuredPublicUrl } from "./public-url.js";
4
5
  import { getLogger } from "./log.js";
5
6
  const log = getLogger('mcp-http');
6
7
  export async function buildMcpServer(role, actor) {
7
8
  const rag = await resolveRagDeps();
8
9
  const tools = (await collectMcpTools({ rag, includeAdmin: role === 'admin', actor })).filter((t) => role === 'admin' || t.role === 'member');
9
- const sections = await buildDomainSections();
10
+ const site = await siteSection(await configuredPublicUrl());
11
+ const sections = [...(await buildDomainSections()), ...(site ? [site] : [])];
10
12
  const server = new McpServer({ name: 'coffer', version: '1.0.0' }, { instructions: buildMcpInstructions(sections) });
11
13
  const registerTool = server.registerTool.bind(server);
12
14
  for (const t of tools) {
@@ -68,6 +68,7 @@ export declare function collectLibraryPurposes(reg?: {
68
68
  }[];
69
69
  }[];
70
70
  }): LibraryPurpose[];
71
+ export declare function siteSection(siteUrl: string): Promise<string | null>;
71
72
  export declare function buildDomainSections(): Promise<string[]>;
72
73
  export declare function collectStarterHints(hooks?: Record<string, PluginHooks>, emFactory?: () => EntityManager, reg?: {
73
74
  libraries: {
package/dist/mcp-tools.js CHANGED
@@ -305,6 +305,10 @@ export function collectLibraryPurposes(reg) {
305
305
  : []),
306
306
  }));
307
307
  }
308
+ export async function siteSection(siteUrl) {
309
+ const site = await frontendInstructions(siteUrl);
310
+ return site ? `## web\n${site}` : null;
311
+ }
308
312
  export async function buildDomainSections() {
309
313
  const libraries = collectLibraryPurposes();
310
314
  let overview = null;
@@ -341,14 +345,7 @@ export async function buildDomainSections() {
341
345
  'For duplicates, read both records completely, compare fields/collections/extends/attachments, recommend the less complete record for trash, and offer a field-by-field merge first. ' +
342
346
  'Use list_trash and restore_record for recovery; purge_record is irreversible and requires explicit confirmation.';
343
347
  const rules = (await collectPluginInstructions()).map(({ id, instructions }) => `## ${id}\n${instructions}`);
344
- const site = await frontendInstructions();
345
- return [
346
- dataModel,
347
- ...(overview ? [overview] : []),
348
- ...(singleSection ? [singleSection] : []),
349
- ...(site ? [`## web\n${site}`] : []),
350
- ...rules,
351
- ];
348
+ return [dataModel, ...(overview ? [overview] : []), ...(singleSection ? [singleSection] : []), ...rules];
352
349
  }
353
350
  export async function collectStarterHints(hooks = pluginHooks, emFactory = () => getEm().fork(), reg) {
354
351
  const parts = [];
@@ -1,3 +1,2 @@
1
1
  export declare function systemTimeZone(): string;
2
2
  export declare function todayDateString(now?: Date, timeZone?: string): string;
3
- export declare function currentEnvironment(now?: Date, timeZone?: string): string;
@@ -12,19 +12,3 @@ function part(now, timeZone, locale, options) {
12
12
  export function todayDateString(now = new Date(), timeZone = systemTimeZone()) {
13
13
  return part(now, timeZone, 'en-CA', { year: 'numeric', month: '2-digit', day: '2-digit' });
14
14
  }
15
- export function currentEnvironment(now = new Date(), timeZone = systemTimeZone()) {
16
- let zone = timeZone;
17
- try {
18
- new Intl.DateTimeFormat('en-CA', { timeZone: zone }).format(now);
19
- }
20
- catch {
21
- zone = 'UTC';
22
- }
23
- const date = part(now, zone, 'en-CA', { year: 'numeric', month: '2-digit', day: '2-digit' });
24
- const weekday = part(now, zone, 'en-US', { weekday: 'long' });
25
- const time = part(now, zone, 'en-GB', { hour: '2-digit', minute: '2-digit', hour12: false });
26
- return [
27
- `Current moment, refreshed on every turn: ${date} (${weekday}), ${time}, timezone ${zone}.`,
28
- 'Resolve every relative date against this value — "today", "tomorrow", "this week", ages, and expiry, warranty or due-date checks. Never infer the date from your training data and never tell the user you cannot know it.',
29
- ].join('\n');
30
- }
@@ -8,7 +8,7 @@ export { makeAttachmentCapabilities } from './agent-capabilities.ts';
8
8
  export { makeSystemCapabilities } from './system-capabilities.ts';
9
9
  export { makeSuggestionCapabilities } from './suggestion-capabilities.ts';
10
10
  export type { SuggestionCapability } from './suggestion-capabilities.ts';
11
- export { currentEnvironment, systemTimeZone } from './environment.ts';
11
+ export { systemTimeZone } from './environment.ts';
12
12
  export { inspectUpload, isAgentToolContentResult } from './file-inspection.ts';
13
13
  export type { PipelineDeps, RunAgentFn } from './pipeline.ts';
14
14
  export { buildPolicy, loadGatePolicy, loadAgentId } from './config.ts';
@@ -17,7 +17,7 @@ export { isSenderAllowed } from './allow.ts';
17
17
  export { makeLiveChannel, plainRender } from './live-message.ts';
18
18
  export type { LiveChannelOps, LiveChannelOpts, RenderFn } from './live-message.ts';
19
19
  export { chunk } from './format.ts';
20
- export type { Connector, IncomingConversation, GatePolicy, ReplyContext, ReplyPayload, ReplyChannel, AttachmentRef, AttachmentMaterializer, AgentToolDefinition, AgentToolProvider, ConvMessage, SystemLayer, AgentRequest, AgentResult, AgentRuntime, AgentCapabilities, AgentPreset, AgentDescriptor, ConnectorRegistration, AgentToolContentBlock, AgentToolContentResult, } from './types.ts';
20
+ export type { Connector, IncomingConversation, GatePolicy, ReplyContext, ReplyPayload, ReplyChannel, AttachmentRef, AttachmentMaterializer, AgentToolDefinition, AgentToolProvider, ConvMessage, AgentRequest, AgentResult, AgentRuntime, AgentCapabilities, AgentPreset, AgentDescriptor, ConnectorRegistration, AgentToolContentBlock, AgentToolContentResult, } from './types.ts';
21
21
  export declare function startOrchestrator(): void;
22
22
  export declare function stopOrchestrator(): void;
23
23
  export declare const orchestratorStartersTask: BackgroundTask;
@@ -12,7 +12,7 @@ export { attachmentMaterializer } from "./attachments.js";
12
12
  export { makeAttachmentCapabilities } from "./agent-capabilities.js";
13
13
  export { makeSystemCapabilities } from "./system-capabilities.js";
14
14
  export { makeSuggestionCapabilities } from "./suggestion-capabilities.js";
15
- export { currentEnvironment, systemTimeZone } from "./environment.js";
15
+ export { systemTimeZone } from "./environment.js";
16
16
  export { inspectUpload, isAgentToolContentResult } from "./file-inspection.js";
17
17
  export { buildPolicy, loadGatePolicy, loadAgentId } from "./config.js";
18
18
  export { getConversationStarters, refreshSystemStarters } from "./starters.js";
@@ -101,15 +101,15 @@ export async function handleIncoming(connector, conversation, deps) {
101
101
  const preparedMessages = conversation.prepareAttachments
102
102
  ? await safeCall(() => conversation.prepareAttachments(attachmentMaterializer), messages, 'prepareAttachments')
103
103
  : messages;
104
- const agentMessages = policy.triggerPrefix
105
- ? preparedMessages.map((m, i) => (i === preparedMessages.length - 1 ? { ...m, content: queryText } : m))
106
- : preparedMessages;
104
+ const agentMessages = preparedMessages.map((m, i) => i === preparedMessages.length - 1
105
+ ? {
106
+ ...m,
107
+ ...(policy.triggerPrefix ? { content: queryText } : {}),
108
+ ...(conversation.turnContext ? { context: conversation.turnContext } : {}),
109
+ }
110
+ : m);
107
111
  const base = await agentBase();
108
- const system = buildSystem({
109
- base,
110
- channelSystem: conversation.channelSystem,
111
- volatileSystem: conversation.volatileSystem,
112
- });
112
+ const system = buildSystem({ base, channelSystem: conversation.channelSystem });
113
113
  db?.logTurn({
114
114
  connector: connectorId,
115
115
  chatId,
@@ -1,7 +1,4 @@
1
- import type { SystemLayer } from './types.ts';
2
1
  export declare function buildSystem(input: {
3
2
  base: string;
4
3
  channelSystem?: string;
5
- volatileSystem?: string;
6
- environment?: string;
7
- }): SystemLayer[];
4
+ }): string;
@@ -1,13 +1,3 @@
1
- import { currentEnvironment } from "./environment.js";
2
1
  export function buildSystem(input) {
3
- const text = [input.base, input.channelSystem].filter(Boolean).join('\n\n');
4
- const layers = [{ text, stable: true }];
5
- const environment = input.environment ?? currentEnvironment();
6
- const volatile = [environment, input.volatileSystem]
7
- .map((part) => part?.trim())
8
- .filter(Boolean)
9
- .join('\n\n');
10
- if (volatile)
11
- layers.push({ text: volatile, stable: false });
12
- return layers;
2
+ return [input.base, input.channelSystem].filter(Boolean).join('\n\n');
13
3
  }
@@ -34,15 +34,12 @@ export interface AgentToolContentResult {
34
34
  export interface ConvMessage {
35
35
  role: 'user' | 'assistant';
36
36
  content: string;
37
+ context?: string;
37
38
  attachments?: AttachmentRef[];
38
39
  sender?: string | null;
39
40
  msgId: string;
40
41
  ts: number;
41
42
  }
42
- export interface SystemLayer {
43
- text: string;
44
- stable: boolean;
45
- }
46
43
  export interface AgentCapabilities {
47
44
  vision?: boolean;
48
45
  documents?: boolean;
@@ -64,7 +61,7 @@ export interface AgentDescriptor {
64
61
  presets: AgentPreset[];
65
62
  }
66
63
  export interface AgentRequest {
67
- system: SystemLayer[];
64
+ system: string;
68
65
  messages: ConvMessage[];
69
66
  toolProvider?: AgentToolProvider;
70
67
  presetId?: string;
@@ -103,7 +100,7 @@ export interface IncomingConversation {
103
100
  presetId?: string;
104
101
  chatId: string;
105
102
  channelSystem?: string;
106
- volatileSystem?: string;
103
+ turnContext?: string;
107
104
  sender: {
108
105
  id: string;
109
106
  displayName?: string;
@@ -12,14 +12,14 @@ export const SYSTEM_SETTINGS = defineSettings({
12
12
  label: 'core.settings.language',
13
13
  default: 'uk',
14
14
  strict: true,
15
- view: { noSearch: true },
15
+ noSearch: true,
16
16
  options: [
17
17
  { value: 'uk', title: 'Українська' },
18
18
  { value: 'ru', title: 'Русский' },
19
19
  { value: 'en', title: 'English' },
20
20
  ],
21
21
  }),
22
- agent_id: field.string({ label: 'core.settings.agent_id', strict: true, view: { noSearch: true } }),
22
+ agent_id: field.string({ label: 'core.settings.agent_id', strict: true, noSearch: true }),
23
23
  access_password: field.password({ label: 'core.settings.access_password' }),
24
24
  trigger_prefix: field.string({ label: 'core.settings.trigger_prefix' }),
25
25
  reply_window: field.int({ label: 'core.settings.reply_window', default: 1800 }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffer-org/server",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24"
@@ -36,7 +36,7 @@
36
36
  "postpack": "node ../../scripts/swap-exports.mjs src"
37
37
  },
38
38
  "dependencies": {
39
- "@coffer-org/sdk": "^4.0.0",
39
+ "@coffer-org/sdk": "^5.0.0",
40
40
  "@extractus/oembed-extractor": "^4.1.0",
41
41
  "@fastify/cors": "^11.2.0",
42
42
  "@fastify/multipart": "^10.0.0",