Skip to content
中文

Presentation: field ownership and final output ​

The model fills only the fields it is assigned; fixed text, bound values, and semantic keys are owned by the program.

defineOutputCatalog supports text, master, record, and group outputs. Non-group outputs must declare fields; text may have only one required field, and master template slots must correspond exactly to the fields. Field owner is generated, bound, constant, or semantic. Without valueSchema the string parser is used.

toModelSchema exposes only generated/semantic fields to the model, with semantic limited to the allowed keys; check returns a check status and issues, and compose({outputId,input},context) synchronously binds real values after checks and returns {outputId,kind,value}. bound/semantic require a registered provider, and providers must be synchronous. group items are assigned by the program, and references must be registered and must not form a cycle.

defineReplyFormats declares a format only where the App really owns a reply template; resolve returns undefined for every other reply, so no extra output requirement or follow-up question is added. replyFormatChecks provides bubble-count and total-character budget checks, and mergeReplyBubbles drops blank bubbles and merges overflow into the last one. Limits, templates and wording stay with the App.

The output contract rejecting model-filled extra fields does not mean the business is complete, authorized, or already sent to the user. Final output, streaming, and business submission remain separate boundaries.

Progressive examples for the same business case ​

First compose one piece of generated text ​

Beginner · Node.js

ts
import { Presentation } from '@jangts/agent-core/kits/presentation';
const outputs = Presentation.defineOutputCatalog([
  { id: 'reply', kind: 'text', fields: [{ id: 'text', owner: 'generated' }] },
]);
console.log(outputs.toModelSchema('reply'));
const output = outputs.compose({ outputId: 'reply', input: { generated: { text: '普通对象即可定义节点。' } } }, { app: {}, signal: new AbortController().signal });
console.log(output.value);
js
import { Presentation } from '@jangts/agent-core/kits/presentation';
const outputs = Presentation.defineOutputCatalog([
    { id: 'reply', kind: 'text', fields: [{ id: 'text', owner: 'generated' }] },
]);
console.log(outputs.toModelSchema('reply'));
const output = outputs.compose({ outputId: 'reply', input: { generated: { text: '普通对象即可定义节点。' } } }, { app: {}, signal: new AbortController().signal });
console.log(output.value);

Let the program own the explanatory prefix in the same compose ​

Configuration · Node.js

ts
import { Presentation } from '@jangts/agent-core/kits/presentation';
const outputs = Presentation.defineOutputCatalog([
  { id: 'reply', kind: 'master', master: '{{prefix}}{{text}}', fields: [
    { id: 'prefix', owner: 'constant', constantValue: '接口说明:' },
    { id: 'text', owner: 'generated' },
  ] },
]);
console.log(outputs.toModelSchema('reply')); // 只有 text 由模型填写
console.log(outputs.compose({ outputId: 'reply', input: { generated: { text: '普通对象即可定义节点。' } } }, { app: {}, signal: new AbortController().signal }).value);
js
import { Presentation } from '@jangts/agent-core/kits/presentation';
const outputs = Presentation.defineOutputCatalog([
    { id: 'reply', kind: 'master', master: '{{prefix}}{{text}}', fields: [
            { id: 'prefix', owner: 'constant', constantValue: '接口说明:' },
            { id: 'text', owner: 'generated' },
        ] },
]);
console.log(outputs.toModelSchema('reply')); // 只有 text 由模型填写
console.log(outputs.compose({ outputId: 'reply', input: { generated: { text: '普通对象即可定义节点。' } } }, { app: {}, signal: new AbortController().signal }).value);

Add bound fields and semantic keys while keeping the compose entry ​

Extension · Node.js

ts
import { Presentation } from '@jangts/agent-core/kits/presentation';
const outputs = Presentation.defineOutputCatalog<{ displayName: string }>([
  { id: 'reply', kind: 'record', fields: [
    { id: 'text', owner: 'generated' },
    { id: 'author', owner: 'bound', providerId: 'author' },
    { id: 'tone', owner: 'semantic', providerId: 'tone', semanticKeys: ['brief', 'detailed'] },
  ] },
], { providers: [
  { id: 'author', resolve: (_input, { app }) => app.displayName },
  { id: 'tone', resolve: ({ key }) => key === 'brief' ? '简洁说明' : '详细说明' },
] });
const result = outputs.compose({ outputId: 'reply', input: { generated: { text: '普通对象即可。', tone: 'brief' } } }, { app: { displayName: '示例助手' }, signal: new AbortController().signal });
console.log(result.value);
js
import { Presentation } from '@jangts/agent-core/kits/presentation';
const outputs = Presentation.defineOutputCatalog([
    { id: 'reply', kind: 'record', fields: [
            { id: 'text', owner: 'generated' },
            { id: 'author', owner: 'bound', providerId: 'author' },
            { id: 'tone', owner: 'semantic', providerId: 'tone', semanticKeys: ['brief', 'detailed'] },
        ] },
], { providers: [
        { id: 'author', resolve: (_input, { app }) => app.displayName },
        { id: 'tone', resolve: ({ key }) => key === 'brief' ? '简洁说明' : '详细说明' },
    ] });
const result = outputs.compose({ outputId: 'reply', input: { generated: { text: '普通对象即可。', tone: 'brief' } } }, { app: { displayName: '示例助手' }, signal: new AbortController().signal });
console.log(result.value);

Policies & implementations ​

API reference, usage examples and developer guides.