diff --git a/docs/examples/TypeScript/agent.ts b/docs/examples/TypeScript/agent.ts new file mode 100644 index 000000000..ddec769da --- /dev/null +++ b/docs/examples/TypeScript/agent.ts @@ -0,0 +1,126 @@ +import { client } from '@api/sc'; +import { ScAddr, ScConstruction, ScLinkContent, ScTemplate, ScType, ScLinkContentType } from 'ts-sc-client'; + + +export const check = async(action: ScAddr,keynodes: Record) => { + const checkTemplate = new ScTemplate(); + checkTemplate.triple( // класс_действия + keynodes["get_set_power_action"], // | + ScType.EdgeAccessVarPosPerm, // \/ + action, // действие + ); + const checkResult = await client.templateSearch(checkTemplate); + if (checkResult.length==0) + { + return false; + + } + return true; +} + +export const getSetPowerAgent = async(subscribedAddr: ScAddr, foundEdge: ScAddr, actionNode: ScAddr) => { + const getSetPowerAction = "get_set_power_action"; + const action = 'action'; + const actionInitiated = 'action_initiated'; + const actionFinished = 'action_finished'; + const actionFinishedSuccessfully = 'action_finished_successfully'; + const actionFinishedUnsuccessfully = 'action_finished_unsuccessfully'; + const nrelResult = 'nrel_result'; + const nrelSetPower="nrel_set_power"; + const rrel1 = 'rrel_1'; + const baseKeynodes = [ + { id: getSetPowerAction, type: ScType.NodeConstClass }, + { id: rrel1, type: ScType.NodeConstRole }, + { id: nrelResult, type: ScType.NodeConstNoRole }, + { id: nrelSetPower, type: ScType.NodeConstNoRole }, + { id: actionFinished, type: ScType.NodeConstClass }, + { id: actionFinishedSuccessfully, type: ScType.NodeConstClass }, + { id: actionFinishedUnsuccessfully, type: ScType.NodeConstClass }, + { id: action, type: ScType.NodeConstClass }, + { id: actionInitiated, type: ScType.NodeConstClass }, + ]; + const keynodes = await client.resolveKeynodes(baseKeynodes); //собрали все кейноды из БЗ + if(await check(actionNode,keynodes)===false) //сделали проверку на класс действия + { + return; + } + + const setAlias = '_set'; //узел множества + const elAlias = '_el'; //узел элемента множества + const template = new ScTemplate(); + template.triple( // класс_действия + keynodes[getSetPowerAction], // | + ScType.EdgeAccessVarPosPerm, // \/ + actionNode, // действие + ) + template.tripleWithRelation( + actionNode, // действие + ScType.EdgeAccessVarPosPerm, // ||<--rrel_1(аргумент) + [ScType.NodeVar, setAlias], // \/ + ScType.EdgeAccessVarPosPerm, // множество + keynodes[rrel1], + ) + template.triple( // множество + setAlias, // | + ScType.EdgeAccessVarPosPerm, // \/ + [ScType.NodeVar, elAlias], // элемент + ) + const result=await client.templateSearch(template); + if (!result.length) { //если конструкция не найдена + const finalConstruction= new ScConstruction(); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[actionFinished], actionNode); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[actionFinishedUnsuccessfully], actionNode); + await client.createElements(finalConstruction); + return ; + } + + + const elements:ScAddr[] = []; + for (let i = 0; i < result.length; i++) { //выбираем элемент множества из кажой найденной конструкции(!!!в одной конструкции у множества только один элемент) + elements.push(result[i].get(elAlias)); + } + const set = result[0].get(setAlias); // выбираем узел самого множества из первой найденной конструкции, потому что узел множества он и в Африке узел множества + const power = elements.length.toString();; + + + const powerSetConstruction = new ScConstruction(); //конструкция,где будет только множество и его мощность + const setPowerLinkAlias="set_power_link"; //метки для всех будущих элементов + const edgeCommonSetPowerAlias="edge_common_set_power"; + const edgePosPermSetPowerAlias="edge_pos_perm_set_power"; + const resultConstructionNodeAlias="result_construction_node"; + const edgePosPermResultAlias="edge_pos_perm_result"; + const edgeCommonResultAlias="edge_common_result"; + powerSetConstruction.createLink(ScType.LinkConst,new ScLinkContent(power, ScLinkContentType.String),setPowerLinkAlias);//создаем ссылку с числом ссылка + powerSetConstruction.createEdge(ScType.EdgeDCommonConst,set,setPowerLinkAlias,edgeCommonSetPowerAlias); //соединяем ее с множеством дугой для отношений /\ + powerSetConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[nrelSetPower],edgeCommonSetPowerAlias,edgePosPermSetPowerAlias); //соедиянемя nrel_set_power с предыдущей дугой ||<--nrel_set_power + const powerSetRes = await client.createElements(powerSetConstruction); // множестов + if (powerSetRes && powerSetRes.length > 0) { + const resultConstruction = new ScConstruction(); //конструкция,где действие будет соединяться с предыдущей конструкцией отношением nrel_result + resultConstruction.createNode(ScType.NodeConst,resultConstructionNodeAlias); //создаем узел-посредний + resultConstruction.createEdge(ScType.EdgeDCommonConst,actionNode,resultConstructionNodeAlias,edgePosPermResultAlias);// соединяем с действием дугой для отношений + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[nrelResult],edgePosPermResultAlias,edgeCommonResultAlias); //соедиянемя nrel_result с предыдущей дугой + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm,resultConstructionNodeAlias,powerSetRes[powerSetConstruction.getIndex(setPowerLinkAlias)]);// соединяем узел-посредний со всеми элементами powerSetConstruction + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm,resultConstructionNodeAlias,set); + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm,resultConstructionNodeAlias,powerSetRes[powerSetConstruction.getIndex(edgeCommonSetPowerAlias)]); + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm,resultConstructionNodeAlias,powerSetRes[powerSetConstruction.getIndex(edgePosPermSetPowerAlias)]); + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm,resultConstructionNodeAlias,keynodes[nrelSetPower]); + const resultRes = await client.createElements(resultConstruction); + if (resultRes && resultRes.length > 0) { + const finalConstruction= new ScConstruction(); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[actionFinished], actionNode); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[actionFinishedSuccessfully], actionNode); + await client.createElements(finalConstruction); + return ; + } + const finalConstruction= new ScConstruction(); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[actionFinished], actionNode); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[actionFinishedUnsuccessfully], actionNode); + await client.createElements(finalConstruction); + return ; + } + const finalConstruction= new ScConstruction(); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[actionFinished], actionNode); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm,keynodes[actionFinishedUnsuccessfully], actionNode); + await client.createElements(finalConstruction); + return ; +}; \ No newline at end of file diff --git a/docs/examples/TypeScript/client.ts b/docs/examples/TypeScript/client.ts new file mode 100644 index 000000000..2bc7a994e --- /dev/null +++ b/docs/examples/TypeScript/client.ts @@ -0,0 +1,23 @@ +import { SC_URL } from '@constants'; +import { ScClient,ScType,ScEventParams,ScEventType } from 'ts-sc-client'; +import { getSetPowerAgent } from "@agents/agent" + +async function testAgent() { + const actionInitiated = "action_initiated"; + const keynodes = [ + { id: actionInitiated, type: ScType.NodeConstNoRole }, + ]; + + const keynodesAddrs = await client.resolveKeynodes(keynodes); + + const eventParams = new ScEventParams(keynodesAddrs[actionInitiated], ScEventType.AddOutgoingEdge, getSetPowerAgent); + await client.eventsCreate([eventParams]); +} + +export const client = new ScClient(SC_URL); +testAgent(); + + + + + diff --git a/docs/index.md b/docs/index.md index 696a4891a..f6510b85c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,46 +8,47 @@ At its core, sc-machine operates as a **graph database management system**, enab Table of contents: -- [Quick Start](quick_start.md) - *get up and running with sc-machine quickly* +- [Quick start](quick_start.md) - *get up and running with sc-machine quickly* - [Docker](docker.md) - *get up and running with sc-machine in docker* -- **User Guides** - *detailed instructions on implementing agents* +- **User guides** - *detailed instructions on implementing agents* * C++ Guides - *guidelines for implementing agents on C++* - * [C++ Simple Guide for Implementing Agent](sc-memory/api/cpp/guides/simple_guide_for_implementing_agent.md) - * [Migrate to New Agent API](sc-tools/migrate_to_new_agent_api.md) - *description of script that can be used to migrate to new C++ Agents API* + * [C++ Simple guide for implementing agent](sc-memory/api/cpp/guides/simple_guide_for_implementing_agent.md) + * [Migrate to new agent API](sc-tools/migrate_to_new_agent_api.md) - *description of script that can be used to migrate to new C++ Agents API* - **API** - *comprehensive documentation for C++, Python, and TypeScript APIs* * C++ API - *detailed guides on using the core and extended APIs for interacting with sc-memory* * [C++ Core API](sc-memory/api/cpp/core/api.md) - *documentation of C++ core API for creating, retrieving and erasing sc-elements in sc-memory* * C++ Extended API - *documentation of C++ extended API for manipulating with system identifiers of sc-elements and sc-templates* - * [C++ System Identifier API](sc-memory/api/cpp/extended/helper_api.md) - *documentation of C++ extended API for manipulating with system identifiers of sc-elements* + * [C++ System identifier API](sc-memory/api/cpp/extended/helper_api.md) - *documentation of C++ extended API for manipulating with system identifiers of sc-elements* * [C++ ScTemplate API](sc-memory/api/cpp/extended/template_api.md) - *documentation of C++ extended API for creating and retrieving graphs (it is very useful when you want to work big sc-constructions)* * C++ Agents API - *documentation of C++ Agents API for creating agents* * [C++ Events API](sc-memory/api/cpp/extended/agents/events.md) - *enables developers to create and manage events within the sc-machine, allowing agents to respond dynamically to various triggers* - * [C++ Event Subscriptions API](sc-memory/api/cpp/extended/agents/event_subscriptions.md) - *details how agents can subscribe to specific events and receive notifications when those events occur* + * [C++ Event subscriptions API](sc-memory/api/cpp/extended/agents/event_subscriptions.md) - *details how agents can subscribe to specific events and receive notifications when those events occur* * [C++ Waiters API](sc-memory/api/cpp/extended/agents/waiters.md) - *allows developers to implement wait conditions that pause agent execution until specified conditions are met or events are triggered* * [C++ Keynodes API](sc-memory/api/cpp/extended/agents/keynodes.md) - *provides functionality for creating, retrieving, and manipulating keynodes, which represent significant concepts within the knowledge graph* * [C++ Actions API](sc-memory/api/cpp/extended/agents/actions.md) - *outlines how to define and initiate actions that agents can perform, detailing their arguments and results* * [C++ Agents API](sc-memory/api/cpp/extended/agents/agents.md) - *focuses on agent creation and management* - * [C++ Agent Context API](sc-memory/api/cpp/extended/agents/agent_context.md) - *explains how to manage the context in which agents operate* + * [C++ Agent context API](sc-memory/api/cpp/extended/agents/agent_context.md) - *explains how to manage the context in which agents operate* * [C++ Modules API](sc-memory/api/cpp/extended/agents/modules.md) - *describes how to register agents in an application* * Python API - *documentation on using the Python client for interacting with sc-memory* * [Python Core API](https://github.com/ostis-ai/py-sc-client) - *documentation of Python core API for creating, retrieving and erasing sc-elements and sc-events in sc-memory* * [Python Extended API](https://github.com/ostis-ai/py-sc-kpm) - *documentation of Python extended API for manipulating with large graphs* * TypeScript API - *documentation on using the TypeScript client for interacting with sc-memory* * [TypeScript Core API](https://github.com/ostis-ai/ts-sc-client) - *documentation of TypeScript core API for creating, retrieving and erasing sc-elements and sc-events in sc-memory* - * [sc-element Types](scs/sc_element_types.md) - *detailed description of supported element types* + * [Typescript Simple guide for implementing agent](sc-memory/api/typescript/ts_agent_guide.md) - *documentation of Typescript API provided by ts-sc-client* + * [sc-element types](scs/sc_element_types.md) - *detailed description of supported element types* * [SCs-code](scs/scs.md) - *documentation on SCs Language with examples* - **Tools** - *information on various tools that enhance your experience with sc-machine* - * [Knowledge Base Builder](sc-tools/sc_builder.md) - *description of options of sc-builder for knowledge base sources* - * [Knowledge Base Repo File](sc-tools/kb_repo_file.md) - *description of configuration of knowledge base sources* + * [Knowledge Base builder](sc-tools/sc_builder.md) - *description of options of sc-builder for knowledge base sources* + * [Knowledge Base repo file](sc-tools/kb_repo_file.md) - *description of configuration of knowledge base sources* * [sc-machine Runner](sc-tools/sc_machine.md) - *description of options of sc-machine runner* -- **Build Instructions** - *guidelines for building the project, configuring settings* - * [Quick Start for Developers](build/quick_start.md) - *get up and start developing sc-machine quickly* - * [Build System](build/build_system.md) - *how to build the project and use it as a library* +- **Build instructions** - *guidelines for building the project, configuring settings* + * [Quick start](build/quick_start.md) - *get up and start developing sc-machine quickly* + * [Build system](build/build_system.md) - *how to build the project and use it as a library* * [CMake Flags](build/cmake_flags.md) - *description of CMake flags used to configure sc-machine* * [Configuration File](build/config.md) - *description of a configuration file of sc-machine* - **Development** - *guidelines for contributing to development* * [Contributing Guide](https://github.com/ostis-ai/sc-machine/blob/main/CONTRIBUTING.md) - *guide for those who wants to make contribution into sc-machine* - * [Code Style Guide](dev/codestyle.md) - *guide for those who wants to write code for sc-machine* + * [Codestyle Guide](dev/codestyle.md) - *guide for those who wants to write code for sc-machine* * [Dev Container](dev/devcontainer.md) - *guide for those who wants to develop sc-machine via docker* - [License](https://github.com/ostis-ai/sc-machine/blob/main/COPYING.MIT) - [Changelog](changelog.md) diff --git a/docs/sc-memory/api/typescript/images/get_set_power_agent_input_construction.png b/docs/sc-memory/api/typescript/images/get_set_power_agent_input_construction.png new file mode 100644 index 000000000..940b8c531 Binary files /dev/null and b/docs/sc-memory/api/typescript/images/get_set_power_agent_input_construction.png differ diff --git a/docs/sc-memory/api/typescript/images/get_set_power_agent_output_construction.png b/docs/sc-memory/api/typescript/images/get_set_power_agent_output_construction.png new file mode 100644 index 000000000..41a52b62f Binary files /dev/null and b/docs/sc-memory/api/typescript/images/get_set_power_agent_output_construction.png differ diff --git a/docs/sc-memory/api/typescript/ts_agent_guide.md b/docs/sc-memory/api/typescript/ts_agent_guide.md new file mode 100644 index 000000000..511f0e9fc --- /dev/null +++ b/docs/sc-memory/api/typescript/ts_agent_guide.md @@ -0,0 +1,463 @@ + + +# **Реализация агента на TypeScript** + +!!! note + Руководство актуально только для sc-machine версии 0.10.0 и больше. +--- + + +Агенты в TypeScript создаются преимущественно при работе с sc-memory через сеть. Рассмотрим создание агента на примере TypeScript агентов ostis-системы NIKA. +Для реализации агента в TypeScript, необходимо выполнить следующую последовательность шагов: + +1. Укажите входную (инициализирующую) конструкцию и выходную (результирующую) конструкцию Вашего будущего агента в SC-коде. +2. Создайте файл `client.ts` и создайте экземпляр класса `ScClient` (клиента sc-server). +3. Создайте файл агента и укажите функции, реализующие программму работы агента. +4. Реализуйте основную программу Вашего агента. +5. Зарегистрируйте агента. Создание функции установления условия реакции агента на sc-событие в `client.ts`. + +--- + +Рассмотрим пример реализации агента для подсчета мощности данного множества: + +### **1. Опишите входные и выходные конструкции Вашего агента.** + +Первоначальная конструкция для вызова агента может выглядеть так: + +```scs +..action +<- get_set_power_action; +<- action_initiated; +-> rrel_1: ..some_set;; + +..some_set +-> ..element_1; +-> ..element_2; +-> ..element_3;; +``` + + + +Конструкция результата может быть представлена так: + +```scs +..some_action +=> nrel_result: [* + ..some_set => nrel_set_power: [3];; +*];; +``` + + + +--- + +### **2. Создайте файл `client.ts` и создайте экземпляр класса `ScClient` (клиента sc-server).** + +По умолчанию `sc-machine` содержит `sc-server`, т. е. способ взаимодействия с базой знаний через сеть. +Для взаимодействия с ней используется класс `ScClinet`, являющимся составляющей `ts-sc-client`. Данный класс предоставляет множественные методы для работы с sc-server. Для того, чтобы использовать методы, требуется создать экземпляр класса `ScClinet`. +Более подробную информацию о ts-sc-client и его методах и классах см. [в этом разделе](https://github.com/ostis-ai/ts-sc-client?tab=readme-ov-file). + +Для начала создайте файл `client.ts`, где будет создан экземпляр класса `ScClinet` и, соответственно, зарегистрирован агент. + +Рекомендуется размещать файлы агента примерно следующим образом: + +```plaintext +interface/ +├──api/ +│ ├──sc/ +│ │ ├──client.ts +│ │ └──agents/ +``` + +**client.ts** + +```typescript +import { SC_URL } from '@constants'; +// SC_URL: в ostis-системе NIKA "SC_URL" является описанный заранее WebSocket +//localhost адрес базы знаний ('ws://localhost:8090') +// Однако адрес можно указать явно при создании объекта ts-sc-client +import { ScClient,ScType,ScEventParams,ScEventType } from 'ts-sc-client'; +// Импортирование класса ScClient и необходимых методов для регистрации агента, +//a это: типы sc-элементов (ScType), параметры регистрации агента (ScEventParams) +``` + +--- + +### **3. Создайте файл агента и проверьте, инициализирован ли Ваш агент.** + +Для начала работы следует указать функцию, проверяющую, принадлежит ли инициированное действие классу Вашего агента. Данная функция будет вызываться в основной функции при регистрация агента. Рассмотрим самое распространненное sc-событие, на которое реагирует агент - проведение дуги от узла класса инициированного дейсвия. +Класс инициированного действия существует в базе знаний с идентификатором `action_initiated`. Используйте его для таких событий, как проведение дуги к узлу действия (в примере входной конструкции это узел `some_action`) + + + +Создадим файл агента: + +```diff + interface/ + ├──api/ + │ ├──sc/ + │ │ ├──client.ts + │ │ ├──agents/ ++│ │ │ └──agent.ts +``` + +**agent.ts** + +```typescript +import { client } from '@api/sc'; +//Подключение созданного ранее файла +import { ScAddr, ScConstruction, ScLinkContent, ScTemplate, ScType, +ScLinkContentType } from 'ts-sc-client'; +//Импортирование требуемых классов и методов + + +//Для начала следует создать функцию проверки, которая будет вызываться при +//реакции агента на sc-событие +//в качестве аргументов нам понадобится адрес узла конкретного +//инициализированного действия (action) и список ключевых sc-элементов, +// которые этот агент использует во время выполнения своей программы (keynodes). +// Подробнее о keynodes будет будет рассказано в разделе 4. +export const check = async(action: ScAddr,keynodes: Record) => { + //Создание ScTemplate для последующего поиска по шаблону. + const checkTemplate = new ScTemplate(); + checkTemplate.triple( // класс_Вашего_агента + keynodes["get_set_power_action"], // | + //Или любое другое название | + // класса Вашего агента | + ScType.EdgeAccessVarPosPerm, // \/ + action, // действие + ); + const checkResult = await client.templateSearch(checkTemplate); + if (checkResult.length==0) + //Проверяется, найдена ли данная структура в базе знаний + { + return false; + + } + return true; +} + +``` + +Данная функция реализовывает поиск по шаблону для определения, принадлежит ли узел инициированного действия (`action`) классу Вашего агента. + +В процессе создания `checkTemplate` используются переменные, существование которых требуется проверить. Функция `templateSearch` +ищет данную конструкцию с константными элементами и, при нахождении, возвращает в переменную (См. [документацию ts-sc-client](https://github.com/ostis-ai/ts-sc-client?tab=readme-ov-file)). + + +--- + +### **4. Реализуйте основную программу Вашего агента.** + +Теперь, когда Вы убедились, что именно Ваш агент инициализирован, он должен выполнить все предназначенные ему действия. +Давайте реализуем функцию агента, которая будет выполнять роль основной программы и подаваться в качестве аргумента при регистрации агента. + +Для начала следует определить ключевые узлы, с которыми взаимодействует агент, найти их в базе знаний и интегрировать их в программу. +Для каждого агента можно указать ключевые sc-элементы, которые этот агент использует во время выполнения своей программы. Эти ключевые sc-элементы — это sc-элементы, которые агент не генерирует, а использует в процессе поиска или создания связей между сущностями в базе знаний. Ключевые sc-элементы называются keynodes. + +!!! warning + Sc-keynode элемент нельзя создать без системного идентификатора. + +!!! warning + Все ключевые узлы должны быть статическими объектами. Это значит, что ключевые узлы требуется определять как статические объекты везде (не только в классах). + + +**agent.ts** + +```typescript +//Определим sc-keynodes в основной функции "getSetPowerAgent", которая позже +// будет подаваться в качестве аргумента при регистрации агента. +export const getSetPowerAgent = async(subscribedAddr: ScAddr, foundEdge: ScAddr, +actionNode: ScAddr) => { +//В случае, когда агент реагирует на такое событие как провдение sc-дуги, +//основная функция принимает в каечтсве аргументов узел, от которого проведен +//sc-коннектор (событие), sc-коннектор и узел действия + + const getSetPowerAction = "get_set_power_action"; + + //Для начала укажите класс вашего агента + const action = 'action'; + //узел действия, которое к которому проводиться коннектор + //как одно из sc-событий. + + const actionInitiated = 'action_initiated'; + //Класс инициированного действия + //Требуется для определения инициализации действия + + const actionFinished = 'action_finished'; + //Узел, указывающий о завершении агента. + //От узла проводится коннектор как событие завершения агента + + //Агент может завершиться успешно (actionFinishedSuccessfully) при + //удачном решении делегированной ему задачи + //агент может завершиться неуспешно (actionFinishedUnsuccessfully), + //это означает, что делегированная задача не была решена + const actionFinishedSuccessfully = 'action_finished_successfully'; + const actionFinishedUnsuccessfully = 'action_finished_unsuccessfully'; + + const nrelResult = 'nrel_result'; + //'nrel_result' узел требуется для построения выходной конструкции + //в последующем и указании результат работы агента + const nrelSetPower="nrel_set_power"; + //Неролевое отношение, указывающее мощность множества + + const rrel1 = 'rrel_1'; + //Ролевое отношение 'rrel_1' служит для указания аргумента, + //передающегося агенту. + + const baseKeynodes = [ + { id: getSetPowerAction, type: ScType.NodeConstClass }, + { id: rrel1, type: ScType.NodeConstRole }, + { id: nrelResult, type: ScType.NodeConstNoRole }, + { id: nrelSetPower, type: ScType.NodeConstNoRole }, + { id: actionFinished, type: ScType.NodeConstClass }, + { id: actionFinishedSuccessfully, type: ScType.NodeConstClass }, + { id: actionFinishedUnsuccessfully, type: ScType.NodeConstClass }, + { id: action, type: ScType.NodeConstClass }, + { id: actionInitiated, type: ScType.NodeConstClass }, + ]; //проведите соответствие между идентификатором sc-keynodes + //и его типом + const keynodes = await client.resolveKeynodes(baseKeynodes); + //функция 'resolveKeynodes' производит поиск существующих указанных ключевых + //элементов в базе знаний и, при их отсутствии, создает новые элементы + //в базе знаний. + + //Далее следует проверить принадлежность инициированного действия + //классу Вашего агента с помощью написанной ранее функции check() + + + if(await check(actionNode,keynodes)===false) + { + return; + } + + //Здесь начинается бизнес-логика Вашей программы + //Пожалуйста, ознакомьтесь с документацией ts-sc-client + //для возможности использования всего функционала + + + //Для того, чтобы найти мощность множества, вам потребуется найти + //Количество элементов множества, являющимся аргументом агента + //Создадим ScTemplate структуру для последующего поиска элементов + const setAlias = '_set'; //узел множества (его идентификатор) + const elAlias = '_el'; //узел элемента множества (его идентификатор) + const template = new ScTemplate(); + template.triple( // класс_действия + keynodes[getSetPowerAction], // | + ScType.EdgeAccessVarPosPerm, // \/ + actionNode, // действие + ) + template.tripleWithRelation( + actionNode, // действие + ScType.EdgeAccessVarPosPerm, // ||<--rrel_1(аргумент) + [ScType.NodeVar, setAlias], // \/ + ScType.EdgeAccessVarPosPerm, // множество + keynodes[rrel1], + ) + template.triple( // множество + setAlias, // | + ScType.EdgeAccessVarPosPerm, // \/ + [ScType.NodeVar, elAlias], // элемент + ) + const result=await client.templateSearch(template); + //каждый элемент 'result' хранит в себе найденную структуру + if (!result.length) { //если конструкция не найдена + const finalConstruction= new ScConstruction(); + //ScConstruction() - класс-строитель sc-элементов + //с помощью данного класса строются графовые структуры элементов, + //которые, с помощью функции createElements(ScConstruction) + //синхронизируются с базой знаний + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[actionFinished], actionNode); + //Аргументы CreateEdge: тип sc-коннектора, область отправления, + //область прибытия. + //В данном примере, так как мощность множества не была найдена, + //проводятся дуги от ключевых элементов 'Actionfinised' + //и 'actionFinishedUnsuccessfully' + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[actionFinishedUnsuccessfully], actionNode); + await client.createElements(finalConstruction); + return ; + } + + + const elements:ScAddr[] = []; + for (let i = 0; i < result.length; i++) { + //C помощью цикла выбирается элемент множества из + // каждой найденной конструкции + //(!!!в одной конструкции у множества только один элемент) + elements.push(result[i].get(elAlias)); + } + const set = result[0].get(setAlias); + //'set' - узел самого множества из первой найденной конструкции, + //так как узлы множества одинаковы во всех конструкциях + const power = elements.length.toString();; + //Подсчитанное множество требуется преобразовать + //в строку для вывода в ScClink + + //На данном этапе основной задачей стоит формирование вызодной + //конструкции с помощью ScConstruction() + + //Примером обычно служит выходная конструкция (см. главу 1) + + + const powerSetConstruction = new ScConstruction(); + //Конструкция,где будет только множество и его мощность + + const setPowerLinkAlias="set_power_link"; + //метки для всех будущих sc-элементов + const edgeCommonSetPowerAlias="edge_common_set_power"; + const edgePosPermSetPowerAlias="edge_pos_perm_set_power"; + const resultConstructionNodeAlias="result_construction_node"; + const edgePosPermResultAlias="edge_pos_perm_result"; + const edgeCommonResultAlias="edge_common_result"; + + + powerSetConstruction.createLink(ScType.LinkConst, + new ScLinkContent(power, ScLinkContentType.String),setPowerLinkAlias); + //Создание ссылки createLink(): тип sc-элемента, + //настраиваемое содержиме ссылки, идентификатор + powerSetConstruction.createEdge(ScType.EdgeDCommonConst,set, + setPowerLinkAlias,edgeCommonSetPowerAlias); + //создание sc-дуги общего вида от узла множества к sc-ссылке + powerSetConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[nrelSetPower],edgeCommonSetPowerAlias,edgePosPermSetPowerAlias); + //создание неролевого отношения мощности множества + const powerSetRes = await client.createElements(powerSetConstruction); + //Функция создания sc-элементов в базе знаний + //и последующая проверка ее создания + if (powerSetRes && powerSetRes.length > 0) { + const resultConstruction = new ScConstruction(); + //Конструкция, где действие будет соединяться + //с предыдущей конструкцией отношением nrel_result + resultConstruction.createNode(ScType.NodeConst, + resultConstructionNodeAlias); + //Создание узла-структуры требуется для проведения sc-дуги + //к нескольким элементам сразу + + + resultConstruction.createEdge(ScType.EdgeDCommonConst,actionNode, + resultConstructionNodeAlias,edgePosPermResultAlias); + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[nrelResult],edgePosPermResultAlias,edgeCommonResultAlias); + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + resultConstructionNodeAlias, + powerSetRes[powerSetConstruction.getIndex(setPowerLinkAlias)]); + //Чтобы получить доступ к sc-элементом из + //другой ScConstruction используйте метод getIndex(element) + + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + resultConstructionNodeAlias,set); + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + resultConstructionNodeAlias, + powerSetRes[powerSetConstruction.getIndex(edgeCommonSetPowerAlias)]); + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + resultConstructionNodeAlias, + powerSetRes[powerSetConstruction.getIndex(edgePosPermSetPowerAlias)]); + resultConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + resultConstructionNodeAlias,keynodes[nrelSetPower]); + const resultRes = await client.createElements(resultConstruction); + if (resultRes && resultRes.length > 0) { + const finalConstruction= new ScConstruction(); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[actionFinished], actionNode); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[actionFinishedSuccessfully], actionNode); + await client.createElements(finalConstruction); + return ; + + //Вы можете переиспользовать переменные типа ScConstruction + //для создания разных структур (finalConstruction) + + } + //В случае, если не удалось создать sc-конструкция resultRes, + // считается, что агент не смог выполнить свою задачу + const finalConstruction= new ScConstruction(); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[actionFinished], actionNode); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[actionFinishedUnsuccessfully], actionNode); + await client.createElements(finalConstruction); + return ; + } + //В случае, если не удалось создать sc-конструкцию powerSetRes, + // считается, что агент не смог выполнить свою задачу + const finalConstruction= new ScConstruction(); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[actionFinished], actionNode); + finalConstruction.createEdge(ScType.EdgeAccessConstPosPerm, + keynodes[actionFinishedUnsuccessfully], actionNode); + await client.createElements(finalConstruction); + return ; +}; +``` + +--- + +### **5. Зарегистрируйте агента.** + +Для того чтобы зарегистрировать агента, требуется написать функцию, связывающую требуемое событие с основной функцией агента, реализующей его программу. + +Реализуем данную функцию в `client.ts`: + + + +**client.ts** + +```typescript +//Это уже прописанная Вами преамбула +import { SC_URL } from '@constants'; +import { ScClient,ScType,ScEventParams,ScEventType } from 'ts-sc-client'; + +//Добавьте основную функцию агента, которая будет подписана на событие +import { getSetPowerAgent } from "@agents/agent" + + +//Функция регистрации агента +//В каечстве примера, событие, на которое реагирует агент, возьмем +//проведение sc-коннектора от класса "action_initiated" +async function registerAgent() { + const actionInitiated = "action_initiated"; + const keynodes = [ + { id: actionInitiated, type: ScType.NodeConstNoRole }, + ]; + + const keynodesAddrs = await client.resolveKeynodes(keynodes); + //Процесс нахождения "action_initiated" в базе знаний + + const eventParams = new ScEventParams(keynodesAddrs[actionInitiated], + ScEventType.AddOutgoingEdge, getSetPowerAgent); + //Создание связи (подписки) между событием и основной функцией Вашего агента + //Функция принимает в качестве аргументов + //узел класса иницированного действия, + //тип события (в данном случае, это проведение sc-коннектора) + //и подписанную функцию программы агента + + await client.eventsCreate([eventParams]); +} + +export const client = new ScClient(SC_URL); +``` + +Для того, чтобы проверить агента, следует вызвать функцию регистрации Вашего агента. +Это можно сделать в любом основном файле Вашего TypeScript проекта. + +## **Часто задаваемые вопросы** + + +- [Могу ли я использовать классы ScIterator3Ptr и ScIterator5Ptr из m_context для поиска ранее созданных sc-конструкций?](#могу-ли-я-использовать-классы-sciterator3ptr-и-sciterator5ptr-из-m_context-для-поиска-ранее-созданных-sc-конструкций) + +- [Чем агенты C++ отличаются от TypeScript? Могу ли я теперь всегда реализовывать только TypeScript агенты?](#чем-агенты-c-отличаются-от-typescript-могу-ли-я-теперь-всегда-реализовывать-только-typescript-агенты) + +### Могу ли я использовать классы ScIterator3Ptr и ScIterator5Ptr из m_context для поиска ранее созданных sc-конструкций? + +К сожалению, не весь функционал C++ Core API отражен в ts-sc-client. Таким образом, некоторые методы объекта класса ScMemoryContext недоступны для реализации в TypeScript, в том числе ScIterator3Ptr и ScIterator5Ptr. + +### Чем агенты C++ отличаются от TypeScript? Могу ли я теперь всегда реализовывать только TypeScript агенты? + +Ввиду особенностей организации sc-памяти и фундаменатльных преимуществ языка программирования C++ таких, как производительность и многофункциональность, агент, реализованный на TypeScript, может уступать агенту C++ по времени совершения операций. Мы рекомендуем использовать язык C++ для реализации агентов со сложной логикой, а TypeScript агенты реализовывать для незамысловатой работы с интерфейсом такой, как взаимодействие с базой знаний для получения структур и вывода их в интерфейс. +