Skip to content
English

从真实目录生成任务范围内的菜单 ​

策略的具体实现如下。

ts
export function defineAgentCatalog<
  App,
  Id extends string,
  Goal extends CatalogGoal<Id>,
  Scope extends CatalogScope,
>(ports: AgentCatalogPorts<App, Id, Goal, Scope>) {
  const ids = ports.goalIds.bind(ports),
    goals = ports.goals.bind(ports),
    scopes = ports.scopes.bind(ports),
    task = ports.currentTask.bind(ports);
  const tools = {
    values: ports.tools.values.bind(ports.tools),
    has: ports.tools.has.bind(ports.tools),
    supports: ports.tools.supportsGoal.bind(ports.tools),
    describe: ports.tools.describe.bind(ports.tools),
  };
  const restrict = ports.restrictToTask !== false;
  const boolean = (value: unknown) =>
    booleanResult(
      value,
      'Catalog predicates must be synchronous',
      'Catalog predicates must return boolean',
    );
  /** Whether one goal is active and its demand metadata currently participates. */
  const goalAvailable = (goal: Goal, app: App): boolean => {
    const tool = goal as Goal & Partial<ModelTool<unknown, unknown, App>>;
    if (!toolActive(tool.active, app)) return false;
    const metadata = tool.asIntent;
    if (metadata === undefined || metadata === true || typeof metadata === 'string') return true;
    if (typeof metadata === 'function') return toolActive(metadata, app);
    return toolActive(metadata.when, app);
  };
  const goalIds = (app: App) => ids(app).filter((id) => boolean(tools.supports(id, app)));
  const goalDelegates = (app?: App) =>
    new Map(
      goals().map((goal) => {
        const metadata = (
          goal as Goal & Partial<import('../../structs/capabilities/model.js').ModelTool>
        ).asIntent;
        const explicit = typeof metadata === 'object' ? metadata.delegates : undefined;
        return [
          goal.id,
          explicit
            ? [...explicit]
            : [
                ...new Set([
                  ...goal.delegates,
                  ...[...tools.values()]
                    .filter(
                      (tool) =>
                        tool.lifecycle?.id &&
                        (app === undefined || toolActive(tool.active, app)) &&
                        (tool.goalIds === 'all' || tool.goalIds.includes(goal.id)),
                    )
                    .map((tool) => tool.lifecycle!.id!),
                ]),
              ],
        ] as const;
      }),
    );
  const goalCatalog = (app: App) => {
    const selected = goalIds(app),
      described = tools.describe('model', app),
      delegates = goalDelegates(app);
    return goals(selected)
      .filter((goal) => goalAvailable(goal, app))
      .map((goal) => {
        const {
          inputSchema: _schema,
          resolve: _resolve,
          active: _active,
          asIntent: _asIntent,
          ...metadata
        } = goal as Goal & Partial<ModelTool<unknown, unknown, App>>;
        const demandDescription =
          typeof _asIntent === 'string'
            ? _asIntent
            : typeof _asIntent === 'object' && _asIntent !== null
              ? _asIntent.description
              : undefined;
        return {
          ...metadata,
          ...(demandDescription ? { description: demandDescription } : {}),
          delegates: delegates.get(goal.id) ?? [...goal.delegates],
          scopeIds: scopes([goal.id]).map((scope) => scope.id),
          toolIds: described
            .filter((tool) => tool.goalIds.includes(goal.id))
            .map((tool) => tool.id),
        };
      });
  };
  const scopeCatalog = (app: App) =>
    scopes(goalCatalog(app).map((goal) => goal.id)).map((scope) => ({
      ...scope,
      toolIds: scope.toolIds.filter(tools.has),
    }));
  return Object.freeze({
    goalIds,
    goalDelegates,
    goalCatalog,
    scopeCatalog,
    modelCatalog(app: App) {
      const accepted = restrict ? task(app) : undefined,
        selected = goalIds(app).filter((id) => !accepted || id === accepted.goalId),
        available = goalCatalog(app).filter((intent) => selected.includes(intent.id));
      return {
        availableGoalIds: available.map((intent) => intent.id),
        availableGoals: available.map((intent) =>
          accepted ? { ...intent, scopeIds: accepted.scopeId ? [accepted.scopeId] : [] } : intent,
        ),
        availableScopes: scopeCatalog(app).filter(
          (scope) => !accepted || scope.id === accepted.scopeId,
        ),
        availableTools: tools
          .describe('model', app)
          .filter((tool) => !accepted || tool.goalIds.includes(accepted.goalId)),
      };
    },
  });
}

接口参考、使用示例与开发指南。