Methods of the platform services
The methods of the services of the platform: settings, languages, observation and the journal, sources, the door for programs, the assistant and the profile.
Introduction
The document is a part of the contract Exchange with the kernel: the methods of the functions of the platform used by the workshop and other parts. The levels of settings and languages — Settings, what the platform writes about itself — The make-up of the platform, 3.8. The refusal codes — Error codes.
1 Settings
The files of the levels belong to the function of settings (Settings, section 1). The level session is only the memory of the function, not a file.
settings.get—{ "key" }or all values; withprocess_idit adds the keys of the process; the session covers everything. Withlevel: "process"andprocess_id— only the values written at the level of the process, as they are written: so the export of a process takes them;settings.set—{ "key", "value", "level" }(core|system|user|process|session);processneedsprocess_idand takes, besides the keys of schemas, a free key of the process — a name a parameter of a node names as${name}([A-Za-z_][A-Za-z0-9_]*), without a schema and without checking the value; at other levels a key without a schema issettings_unknown_key; withoutlevel—user;sessionwrites no file; the keyscore.*at levels other thansessionalways go intoconfig/core.json. The answer is{ key, value, level, restart }, wherelevelis the level the value was actually written to; the eventsettings.changed—{ key, level, restart };settings.reset—{ "key" },{ "prefix": "ui." }or{ "group": "core" | "ui" | "other" }; optionallylevel, forprocess—process_id: take an override off a level (the key is removed from the file or from the session), the value is taken again from the schema and the lower levels; withoutlevel—core.*fromconfig/core.json, the others fromconfig/user.json, and all named keys from the session: a reset without a level returns the default. The answer is{ keys, values, level }:values— the values of the keys after the reset,level— the level of the reset, and with nolevelin the request —core,userormixed, if keys of both kinds were taken off; the eventsettings.changed—{ reset: keys, level };settings.ensure—{ "level": "process", "process_id" }: make an empty settings document of the process if there is none;settings.schema— the schemas of all owners:{ "sections": [{ "id", "owner", "group", "keys": [key, …] }], "keys": { key: { "type", "default", "default_by"?, "restart", "min"?, "max"?, "choices"?, "section", "group", "owner" } } }. The subsections go by the large sections (core,ui,other), inside a section — by the id of the owner, within an owner — in the order of its schema file. There are no texts in the answer: the window takes them from the dictionary by the keyssetting.*(Settings, section 2);settings.schema.register—{ "schema" }, whereschemais the content of the schema file of the owner (ogas.settings-schema/1). The owner is whoever the kernel names as the sender of the call (source, Exchange with the kernel, section 3): keys and subsections only with the prefix{owner}.; a repetition of the same owner replaces its schema whole, and the owner repeats the registration when the function of settings comes up anew (function.ready); a foreign key or a schema with an error —settings_invalid, the schema of another owner —settings_invalid_owner. The answer is{ "owner", "keys" }. It publishessettings.schema.registered—{ function_id, keys }: the owner passed the schema of its keys; the values do not change from it, so it is notsettings.changed.- The schema of the keys
core.*the function of settings does not register at itself but gets from the kernel at its start with the querycore.settings.schema. - A value in a file of a level that does not pass the check by the schema is not used: the value of a wider level is taken, and the function publishes
settings.value_invalid{ key, path, value, error_code: "settings_value_invalid", message }— once per file, key and value;messageis a short cause for whoever looks into a refusal by the journal, not a text for the person.
2 Localization
i18n.translate—{ "key", "language"? }: the text of the key in the languagelanguage, without it — in the language of the interface; a language the schema ofi18n.languagedoes not allow is refused withinvalid_request. The answer is{ key, language, text }. The text is given as written in the dictionary: there is no substitution of parameters, the texts of dictionaries do not take them. The folders are its ownfunctions/i18n/localesplus the paths fromcore.locales; when a key is missing in the folders, the key itself is the answer, and the eventi18n.key_missing—{ error_code: "i18n_key_missing", key, language }— opens a problem, one per key;i18n.catalog—{ "language" }(the current one by default): the whole dictionary of a language in one answer{ language, catalog }; the workshop takes it once and looks up keys on its own side;i18n.language.get— a query without parameters: the language of the interface as it is set this minute, and the languages its schema allows,{ language, choices }. Other parts learn the language only so: the settingi18n.languagebelongs to the functioni18nand is not a contract for other parts (Rules of development, 2.6.6);i18n.language.set— a command{ language }: the functioni18nchecks that the language is allowed (otherwiseinvalid_request) and writes its setting itself; the answer is{ language }. So the workshop changes the language without knowing the key of the setting.- The language of the interface is the setting
i18n.languageof the functioni18n; the settings window writes it with an ordinarysettings.set, like any other, andi18n.translate,i18n.catalogandi18n.language.gettake the language from it.
At introduction (handshake) a function may declare locales — relative folders (functions/<id>/locales, modules/<id>/locales). The kernel gives them with the query core.locales. The function i18n does not go round the folders of its neighbours itself.
3 Observability
observe.logs.query—{ "run_id"?, "trace_id"?, "level"?, "limit"? }: the common journallogs/events-<YYYY-MM>.jsonl— from the newest month back untillimitrecords are gathered,logs/events.jsonl, if there is one, last (notcore.jsonl); withrun_id— the file of the run, if there is one. The query writes nothing. No file — an empty list.level—info|warn|error; another value is refused withinvalid_request, not given an empty answer. Withoutlimitthe 50 latest records are given. A half-written tail without\nis not read;observe.logs.remove— a command{ "before": "YYYY-MM" }: deletes the months of the common journal before the named one andlogs/events.jsonl, if its last record is earlier; a month later than the current one is refused withinvalid_request, the current one is never deleted. The answer is{ before, removed }, the names of the deleted files; the deletion is published with the eventlogs.removed{ files, before, by },by—commandorsetting. The months the settingobserve.logs_keep_monthsdoes not keep the function deletes itself the same way — at its start, at the beginning of a month and after the setting is changed.observe.problems.list— optionally{ "status": "open"|"resolved" }: open problems (open: true) or closed ones; another value is refused withinvalid_request, without the field — all. A problem is a grouped refusal (problem_id,code,severity,open,count,first_seen/last_seen), not a copy of each event; its fields — File formats, section 13;observe.problems.resolve—{ "problem_id" }: a command; publishesproblem.resolved.observe.space— a query without parameters:{ parts: [{ key, title_key, bytes, clear_method? }] }— the parts of the room and how much each takes on the disk;title_key— the name of the part in the dictionary of the owner,clear_method— the command that takes away what can be restored in this part (called with{ part: key }); the journals go by months (observe.logs.remove).
4 Sources
The function sources (The workshop, 5.6; threats — Protection, 3.14). It goes to the network with the system program curl, with the proxies and certificates the system sees, and only when it is asked. It reads the showcase of ogas.space only together with its signature by the site key (File formats, 21.5): if the signature does not hold or is missing, sources.search, sources.item and sources.platform refuse with source_signature_bad.
sources.list— a query without parameters:{ sources: [{ source, kind, url, unchecked }] }— the sources by the settings of the function:ogas— the O.G.A.S. showcase,catalog-1,catalog-2… — the showcases ofsources.catalogs,huggingface,civitai. A source with an empty address is not listed.unchecked— a showcase not on ogas.space (the address does not begin withhttps://ogas.space/): nobody checked what is in it; for Hugging Face and Civitai —false, they hold neural networks, not code.sources.facets— a query{ source }: what the source picks by and in what order it gives —{ filters: [{ key, values }], sorts }: for Hugging Face the filterstaskandlibrary, for Civitai —typeandbase, for a showcase —what; the orders —downloads,likes,newest.sources.search— a query{ source, text?, filters?, sort?, related? }:{ items, more }, no more thansources.resultsthings;filters—{ key: value }fromsources.facets,sort— one of its orders,related—{ relation, id }at Hugging Face: models made fromidin this way:quantized,finetune,adapter,merge. A thing —{ id, title, what, kind?, category?, base?, author?, downloads?, likes?, updated?, license?, size?, parameters?, gpu_mb?, profile?, preview },category— the task or type as the source calls them,base— the library at Hugging Face, the base model at Civitai,parameters— how many parameters the network has, if the source names it,gpu_mb— how much video memory a program or module of a showcase needs, if it names it,what—program,module,networkorpiece— a piece of interface,size— bytes, if the source names them,preview— whether the thing has a picture. An emptytext— the whole showcase, at Hugging Face and Civitai — the most downloaded. The request goes to the site of the source.sources.item— a query{ source, id, version? }: the whole thing —{ id, title, what, kind?, category?, author?, license?, description?, page?, gated, files, size, versions, version, version_id, base, relations, gpu_mb?, profile? }:versions— the versions of the thing{ id, name, base?, updated? },version_id— which is shown,version— its name (at Civitai; with noversionin the request — the latest),base— which model it is made from,relations— which relatives it may have (quantized,finetune,adapter,merge);- a file —
{ path, size, sha256?, runs_code, chosen, role, variant? }:role—weights,part:<folder>,adapter,config,tokenizer,vae,docs,pictureorother;variant— how these weights differ from others: the quantization level, the precision, being pruned. When the source names no role and variant, they are read from the file name only for a network, and the files of a program and a module areother, without a variant; runs_code— a format that runs code when read;chosen— what to take if the person did not choose otherwise:.safetensorswhen there are any, and everything exceptruns_code;size— how much the chosen ones weigh;weights— whether the thing has weights at all,safe_weights— whether there are.safetensorsamong them: without them the person chooses the weights themselves;gated— the source demands signing in or agreeing to terms: the platform does not download such a thing.sources.preview— a query{ source, id }: the picture of a found thing for a tile —{ media_type, data },datais the content in base64, or{ media_type: null }if there is none or it is not PNG, JPEG, WebP or GIF. The address is taken from the last search of this source, not from the call; a picture over 2 MiB is not taken (Protection, 3.14).sources.download— a command{ source, id, version?, files, kind?, name? }: begin downloading the filesfiles— paths fromsources.item; a network — with the kindkindand the namenameunder which it will stand in the folder of networks. The answer comes at once —{ download_id, size }, the course — by an event. A refusal before the beginning:source_gated,source_too_big— larger thansources.max_gib,source_no_room— larger than the free room,source_file_bad— a path the thing does not have or that leads out of its folder,model_exists— a network with such a name is already there.sources.download.cancel— a command{ download_id }: stop a download; its folder is removed. No such going download —download_not_found.sources.downloads— a query without parameters:{ downloads }— the downloads of the session in the form of the eventsources.download.changed, the newest first.sources.space— a query without parameters:{ parts: [{ key, title_key, bytes, clear_method? }] }— the parts of the room and how much each takes on the disk;title_key— the name of the part in the dictionary of the owner,clear_method— the command that takes away what can be restored in this part (called with{ part: key }).sources.space.clear— a command{ part: "downloads" }: takes away what was downloaded and not taken in; the folder of a download that goes on stays. Answer{ cleared, removed }.sources.platform— a query{ check? }:{ own, version?, page?, newer, checked }— the number of the platform and what the last look at the showcase of O.G.A.S. said of a new version;check: true— look now. Only the checked showcase (ogas.space) is looked at, and the page of the new version is only a page of that site. The showcase is looked at by the button «Check» in «Status» and at start, if the settingsources.check_on_startis on (on by default); nothing is downloaded or installed by it.- The event
sources.platform.newer—{ own, version, page }: a new version came out; the workshop says so and shows the number in the bar «Platform». - The event
sources.download.changed—{ download_id, source, unchecked, id, title, what, state, done, size, file?, folder?, document?, kind?, name?, error_code?, message? }.state—going,done,failedorcancelled;doneandsize— bytes;file— which file is being downloaded;folder— for a finished program, module and piece of interface the folder indownloads/they are taken in from;document— for a piece its document, whichcanvas.piece.importtakes. While a download goes, the event comes out no more often than once a second.unchecked— the address of a showcase nobody checked, if the download is from there, otherwisenull: the window asks about trust before taking in a program or a module.
5 The door for the person's programs
The function gate is the door through which a program of the person (an OGAS SDK script, an editor) talks to the platform. The door is closed until the setting gate.door is open; closing breaks all connections through it. The function listens over TCP only on 127.0.0.1, the port is the setting gate.port (0 — a free one), at once — no more than gate.clients programs. Where the door is and its key, the function writes into the document data/gate.json (ogas.gate/1): { format, port, key }, port is null while the door is closed. The key is 32 random bytes in hexadecimal; it lives until it is replaced.
The first message of a connection is gate.hello { key, client? }: the right key — the answer { status: "ready" }, a wrong one or another first message — the refusal gate_unauthorized and a closed connection; silence longer than 10 seconds closes the connection; as many programs as the door lets in already — gate_busy. Then the requests of the program go to the kernel, like the requests of the window, and the events of the kernel come to it as the notification event. Not allowed — the refusal gate_not_allowed: the kernel methods except core.status, core.health and core.event.subscribe; the methods gate.* and those of the functions of the window — the ones core.status calls interactive; settings.set of a key gate.*; settings.reset without a key or of a key gate.*.
The methods of the function for the window:
gate.status— a query without parameters:{ open, port, programs, limit }— whether the door is open, its port, how many programs came in and how many it lets in.gate.key— a command without parameters:{ key, document }— the key, for the person to hand to a program themselves, and where it is written. No key yet — the command makes it and writes it; making one failed —gate_no_key.gate.key.renew— a command without parameters: a new key; all programs that came in with the old one leave. The answer is{ renewed: true }.
6 The assistant
The function assistant is the assistant of the workshop: the person writes a task in words, and the network they connected builds programs and modules with the tools of the platform, checks and tries them, and says what it did. A network is a module with "role": "assistant_network" (the input request, the output reply); ready networks come with OGAS SDK in sdk/networks, the key of a network lies in .env of its module and does not get into the function of the assistant.
The access of a task is draft or extended. With draft the assistant changes only the drafts and modules it made itself (their list — data/assistant/own.json, ogas.assistant-own/1), and does not switch programs on. With extended — any programs and modules of the person except the networks of the assistant, and it switches programs on. In no access does the assistant have tools that read secrets, change settings or delete.
A task goes in its own thread: the network answers, the function carries out the tools it called and gives it their answers, until the network answers without tools. A task stops when it has spent assistant.max_steps calls of the network or assistant.task_budget tokens, and waits for assistant.task.go_on. A task is written after each step into data/assistant/tasks/<task_id>.json (ogas.assistant-task/1) and tells of itself with the event assistant.task.changed.
assistant.network.get— a query without parameters:{ format, module_id, params, environment }— the chosen network (ogas.assistant-network/1,data/assistant/network.json).assistant.network.set— a command{ module_id, params?, environment? }: choose a network;environment— the program in whose Python environment the module of the network runs, if it needs packages. A module that is not a network of the assistant —assistant_not_a_network.assistant.task.start— a command{ text, access? }: a new task; the answer is{ task_id }. No network —assistant_no_network.assistant.task.say— a command{ task_id, text, access? }: the person says more in a task; the task goes on. While it works —assistant_task_busy.assistant.task.go_on— a command{ task_id }: a task stopped by its limit goes on with a new limit.assistant.task.stop— a command{ task_id }: the task stops before its next step;{ task_id, stopping }.assistant.task.get— a query{ task_id }: the whole task —{ task_id, title, created, state, access, messages, log, usage, error, working };state—going,answered,stopped,limitorfailed;log— actions{ at, tool, arguments, ok, said }. No such task —assistant_task_not_found.assistant.tasks— a query without parameters:{ tasks: [{ task_id, title, state, created, access }] }, the newest first.- The event
assistant.task.changed—{ task_id, state? , working? }.
7 The profile
The function profile — the person's profile on ogas.space, their parcels, sendings and letters, and what the site says of people: the board of requests, reviews, known bugs, profiles. What guards against what — Protection, section 8; the documents — File formats, section 21. The function goes to the network with the system program curl: it sends only at the person's command, it reads at a command or at start if the setting profile.check_on_start is on. Everything it reads from the site is taken only with a signature by the site key that holds; otherwise — site_signature_bad.
The main key comes into a call as the code (code) or the key file (file — a path, password?) and is forgotten as soon as the call ends.
profile.state— a query without parameters:{ exists, card, number, device, ask_at_start }— whether there is a profile on this computer, its card, the number on the site (if the site named it), the public part of this computer's key;ask_at_start— whether to show the first window (the settingprofile.ask_at_start).profile.create— a command{ card }: a new profile. The answer{ code, parcel }— the recovery code, once, and the parcel of the card that goes to the site (its course — by the eventprofile.sending.changed). There is a profile already —profile_exists.profile.join— a command{ code | file, password?, card }: join this computer to one's profile; the card goes anew. The answer{ parcel }. The code does not hold —key_code_bad; the password does not fit —key_password_bad; the file is notogas.key/1—key_file_bad.profile.key.write— a command{ code, path, password? }: write the key file where the person said; with a password the code in it is encrypted. The answer{ path }.profile.card— a command{ card, code | file, password? }: change the card; it goes as the parcelprofile.profile.revoke— a command{ code | file, password? }: revoke all computers of the profile but this one.profile.delete— a command{ code | file, password? }: delete the profile on the site; the name and the page go, what was sent stays without a name. The profile on this computer is removed once the parcel has gone.profile.leave— a command without parameters: leave the profile on this computer — the keys, sendings and letters of this computer are deleted; the profile on the site stays.profile.send— a command{ what, fields }: a parcel from the computer key,what— a kind from table 13 of «File formats» butprofile,revoke,delete; foroffer, instead of files —things: [{ process_id, version? } | { module_id } | { piece: { id, version?, document } }]: a thing is gathered by its owner — a program with its modules as an export package by the graph function (process.export), a module by the modules function (module.export) — and the profile function takes the folder the owner named in its answer; environments, caches, hidden files and.envdo not go, nor the program built from a module not in Python. Forbugthe function puts in the letter key for the answer itself. The answer at once —{ parcel }, the course — by the event. No profile —profile_none; the fields are not as they must be —parcel_bad; no such thing —thing_not_found; a file in a thing that is neither text nor a picture —thing_binary; a module not in Python withoutCargo.lock—thing_no_lock; over the limits —parcel_too_large.profile.offer.look— a query{ things }, as foroffer: what would go — the files of each thing with sizes, and what would not go and why; it sends nothing.profile.resend— a command{ parcel }: send once more a parcel that did not go; it is signed already, no main key is needed. No such —parcel_not_found.profile.sent— a query without parameters:{ sent, unsent }— one's sendings (ogas.sent/1), newest first, and those signed but not gone:{ id, what, title, made, going },going— whether it goes now. An unsent parcel waits indata/profile/outbox/, and one larger than the limit of a kernel document — in memory until the platform stops.profile.check— a command without parameters: read the states and letters from the site; the answer{ changed, letters }— how many sendings changed state and how many new letters came. The site did not answer —site_unreachable.profile.letters— a query without parameters:{ letters }— the opened letters (ogas.letters/1), newest first.profile.site— a query{ file }:requests,reviewsorprofilesfrom the site, checked by the signature — the board of requests, reviews and known bugs, profiles. The site did not answer —site_unreachable.- The event
profile.changed—{ exists, number }: the profile was made, joined, changed, deleted, or the person left it. - The event
profile.sending.changed—{ parcel, what, state, error_code?, detail? }:state—counting(the counting task),sending,sent,failed; forfailed— the code of the refusal: its own or the site's answerparcel_refusedwith its code indetail. - The event
profile.checked—{ changed, letters }: a look at the site has ended, at start too; the workshop tells of new letters and changed states.