The Manifest
The App manifest fileβ
The manifest.yaml is a required file which defines how the app integrates closely with the user's context and actions.
The manifest is a yaml file listing some simple key/value settings (such as title and description ) and possibly a set of functionalities: filters , transforms , and services as described below. These functionalities work together to expose powerful context-based extensions.
A simple manifest.yamlβ
name: Hello World
version: 1.0.0
description: A very simple iframe type application
icon: fa-hand
The manifest above provides a custom name, title, and icon. This app uses the default docker for a context-free app.
A fully featured manifest.yamlβ
name: Credit Check
version: 1.0.0
image: octostar/code-streamlit
description: Shows a live credit check for the selected person
icon: fa-magnifying-glass-dollar
engine: k8s
entry_point: bash /app/main.sh
memory_limit: 8Gi # App will be killed for OOM and restarted by K8s
memory_requested: 250Mi # App won't even deploy if less memory is available
storage_limit: 10Gi # App will hit "No space left on device"
storage_requested: 1Gi # App will not be even deployed if less storage is available
semantic_bindings:
record_viewer:
- person
watchers:
- name: "check_updates_for_person"
entry_point: bash /app/watcher.sh x
description: "Check if a person has new credit events & notify"
semantically_bound: [ person ]
interval: "20m"
filters:
persons:
type: semantically_bound
concepts:
- person
transforms:
open_credit_check_iframe:
description: opens an iframe
type: iframe
title: '{{ app.folder.os_item_name }}'
icon: fa-magnifying-glass-dollar
enhance_item:
description: Adds some_new_attribute to item
type: javascript
code: |
function transform(item){
item.some_new_attribute = 'hello'
return {item};
}
services:
open_background_check:
role: context_menu
group: open
label: Credit Check
icon: fa-magnifying-glass-dollar
description: Opens the streamlit app passing the person as context for credit check
accepts:
- persons
transforms:
- enhance_item
- open_credit_check_iframe
Dissecting the manifest.yamlβ
Simple key/value settingsβ
name: credit_check
version: 1.0.0
description: Shows a live credit check for the selected person
icon: fa-magnifying-glass-dollar
image: scarduzio/code-streamlit
entry_point: bash /app/main.sh
The name , title and icon for the app are provided. Other options include:
imageto specify a specific docker image used for the app.entry_pointthe command to bootstrap the frontend appno_archiveif true the app zip file is not uploaded/expanded on the server. The commands frommain.shwill be directly executed in the container.url_from_logsif true, the octostar web application will try to extract a url (maybe it contains a token) from the app logs, and include it on the app urlenginethe default isk8s; other options includehtmlandreactwhich require no kubernetes jobrun_as_usercan give the numeric user_id to use if not the default.startup_timeoutcan give the number of seconds to wait if different from the defaultcontainer_portcan give the docker container http port if different from the default (8080)templatethe name of a template to open as the frontend. This can be useful to give a user interface to a fastAPI backend, for example. The template must exist within the templates folder of the app.
Semantic Bindingβ
The optional semantic_binding section provides a way to register the app to feature within the some contexts. Beneath each context are listed the ontology concepts supported by the app.
The following contexts are supported:
record_viewer: The app will appear as a tab in the record viewer.
In this example for a map app, the concepts of person , vehicle , mobile_phone and place are semantically bound to the record_viewer
The semantic binding for person includes priority and maximize properties recognised by the record viewer. In this case if the binding has the highest priority (lower number means higher priority), the app will show in full tab view due to the maximize: true property.
(Note for the record_viewer the record details have a priority of 200 and media gallery has priority of 100)
semantic_bindings:
record_viewer:
- person:
priority: 50
maximize: true
- vehicle
- mobile_phone
- place
Watchersβ
The watchers section contains the list of watcher functions the app exposes. When an app offers a watcher function, users are free to create local entities of type watch_intent in the workspaces containing a reference to the specific watcher function.
watchers:
- name: "check_updates_for_person"
entry_point: bash /app/watcher.sh x
description: "Check new credit events & notify"
semantically_bound: [ person ]
interval: "20m"
In this case, the watcher function named check_updates_for_person, and it can process only entity of type "person". It will run every 20 minutes (minimum interval is 5 minutes).
An example of a watch_intent local entity created by an app or by octostar to reserve the periodic execution of the above watcher function about an entity of type person.
{
"entity_id": "3a96da2f-96ee-40d6-9c5b-882a99829c56",
"entity_type": "os_watch_intent",
"entity_label": "Check new credit events & notify - credit_check - Thomas Jefferson",
"description": "<Normally null, if value is 'STOPPED', this execution will be skipped>",
"previous_run_output": "<base64 encoded value, useful to compare results and finding for differences (optional)>",
"os_last_updated_at": "2024-03-20 11:25:56",
"os_created_by": "operator@octostar.com",
"app_id": "oj-c2-ea-e9e",
"os_last_updated_by": "operator@octostar.com",
"os_workspace": "c43ae201-d175-406e-8f04-f8d1d8b7e402",
"last_run": null,
"watcher_name": "credit_check",
"os_item_type": "os_watch_intent",
"os_entity_uid": "3a96da2f-96ee-40d6-9c5b-882a99829c56",
"arguments": "<base64 encoded JSON representing the arguments for the watcher function (optional), e.g. twitter handle>",
"interval": "20m",
"os_created_at": "2024-03-20 11:25:56"
},
The octostar-python-client pip dependency offers a practical helper to implement watcher functions without worrying much about the details, here is how to use it with an example:
from octostar.utils.watchers import process
def monitor_watcher(w_intent:WatcherIntent) -> Optional[BaseException]:
if w_intent.app_name == "social_monitor":
search_filter = base64_to_dict(w_intent.arguments)
last_ts = base64_to_dict(w_intent.previous_run_output)["last_ts"]
if last_ts:
last_day = last_ts.split(" ")[0]
search_filter["from_date"] = last_day
tweets = get_tweets_from_sl(search_filter)
if tweets:
tweets_df = tweets_records_to_df(tweets, parser=True)
if last_ts:
tweets_df = tweets_df[tweets_df["creation_date"] > last_ts]
last_ts = max(tweets_df["creation_date"])
save_records(tweets_df, [w_intent.os_workspace], w_intent.watcher_name)
if search_filter["notify"]:
notify_about_new_tweets(w_intent, len(tweets_df))
save_new_latest_timestamp.sync(w_intent, last_ts)
process.sync(processor=monitor_watcher)
Filtersβ
The filters section, if provided, lists one or more named re-usable selectors which return a true/false value to accept an offered item/items.
The property names for a filter depend on the filter type . In the example, a semantically_bound filter has a concepts property, listing the concepts which are accepted by the filter. In this case, just one concept is provided: person . Any person record will be accepted by the filter, including records of a type which are a subclass of person , for example student or fisherman.
persons:
type: semantically_bound
concepts:
- person
The following filter types are supported:
semantically_boundβ
As noted above, the semantically_bound filter has a concepts property, which lists one or more accepted concepts.
javascriptβ
Defines an accepts function in javascript code.
is_requirements_txt:
type: javascript
code: |
function accepts(item) {
return item.os_item_name === "requirements.txt";
}
A javascript filter has a code attribute which defines an accepts function which is evaluated in the browser.
In the example above we see the filter returns a true value for an item if the os_item_name attribute equals requirements.txt
pythonβ
Defines an accepts function in python code.
is_a_folder:
type: python
code: |
def accepts(item):
return item["os_item_type"] == "os_folder"
A python filter has a code attribute which defines an accepts function which is evaluated in the browser.
In the example above we see the filter returns a true value for an item if the os_item_type attribute equals os_folder .
For both javascript and python filters, the possible parameters which may be used by the accepts function include:
item : the workspace_item under consideration
items : an array the workspace_item objects under consideration
entities : a list of entities under consideration
workspace : the workspace to which the item or items belong. The full list of items in the workspace can be found in workspace.items property
ee : the EventEmitter
graph : an object having nodes (records /Β entities) and edges
Transformsβ
Transforms are operations taking the accepted context as input, and producing as output either a modification to the context, a visible change to the user interface, or both.
From the example:
enhance_item:
description: Adds some_new_attribute to item
type: javascript
code: |
function transform(item){
item.some_new_attribute = 'hello'
return {item};
}
Above we see a transform named enhance_item . The transform defines in javascript ( type: javascript ) a transform function which adds some_new_attribute to the item parameter, then returned as the item property of the output. In this way the item is effectively and silently transformed: the context to any downstream transform is modified with the updated item parameter.
Also from the example:
open_credit_check_iframe:
description: opens an iframe
type: iframe
title: '{{ app.folder.os_item_name }}'
icon: fa-magnifying-glass-dollar
Above we see a transform of type iframe . The transform opens a new tab in which the app is opened with the default app url (an alternate url could be provided). An icon and title for the tab are given. The iframe transform allows powerful integration with the user interface, for example by using streamlit apps which can communicate directly with the Octostar desktop or server using our APIs.
The full list of available transforms are below:
pythonβ
Executes a python transform function in the browser. The function may be provided either inline using a code attribute, or in a file referenced using the file attribute.
javascriptβ
Executes a javascript transform function in the browser. The function may be provided either inline using a code attribute, or in a file referenced using the file attribute.
nunjucksβ
Executes a nunjucks template transform in the browser. The template may be provided either inline using a template attribute, or in a file referenced using the file attribute.
iframeβ
Opens a tab to the given url attribute, or the default app url. Exposes the browser api to the app using window.message event api as exposed with the octostar streamlit api.
- Note the item(s) exposed within the iframe are referenced as
recordandrecords. - Each record will open in a different tab. To use the same tab include
reuse: true
httpβ
Without opening a tab, invokes a server http operation which can be a service offered by the app (for example a service in a flask app), or an absolute url to an external service. The following optional parameters may be provided:
headersan object for which any attribute can be a nunjucks template or a stringdataan object for which any attribute can be a nunjucks template or a string- note that if the parameter is a string and matches an entry in the transform context, then that context entry is returned. The example below sends the
itemobject as the body of the http POST request.
- note that if the parameter is a string and matches an entry in the transform context, then that context entry is returned. The example below sends the
urlcan be relative to the app url/credit_ratingor an absolute url eg:.https;//example.com/credit_ratingmethoddefault is GET, but POST, PUT etc may be used.
Example
Here is an example of posting an item to a flask service
post_to_flask:
description: Upload the file to flask
type: http
method: POST
url: "{{ app.url }}/upload"
headers:
Content-Type: "application/json"
data: item
Below is an example of a server side flask service which receives the item from the above transform, and returns a notification object:
@app.route('/upload', methods=['POST'])
def notification():
item = request.get_json()
return jsonify({
"notification": {
"message": "Upload Successful!",
"description": f"""The item '{item["entity_label"]}' was successfully uploaded""",
"level": "info"
}
})
emit_eventβ
The emit_event transform provides a powerful way to integrate with the octostar event emitter api.
Emits an event on the EventEmitter. The following parameters are required:
topica string or nunjucks template returning the topic for the event- TODO Make reference to the built-in event topics
- TODO: support shorthand topic names for built-in event topics
argsa list of strings or nunjucks templates returning the arguments for the event emitter.- Note that if the parameter is a string and matches an entry in the transform context, then that context entry is returned. The example below sends the
notificationobject as the parameter to theshowNotificationevent
- Note that if the parameter is a string and matches an entry in the transform context, then that context entry is returned. The example below sends the
Example
emit_notification:
description: Emit notification received from the flask app
type: emit_event
topic: octostar:desktop:builtins:showNotification
args: [ notification ]
Parametersβ
The following parameters may be available to the accept filter and transform functions. The accept filter must check that the parameters it needs are present and acceptable then return true, otherwise it must return false.
-
item: the workspace item under consideration
items: the list of workspace items under considerationworkspace: the relevant Workspace objectgraph: the graph of nodes (Entity[]) and edges (EdgeSpec[])dataTransfer: a dataTransfer like objectentities: the Entity[] to be considered
The following parameters are available to the transforms (but not to the accept filter)
-
OntologyAPI: the OntologyAPI (todo documentation)
DesktopAPI: the DesktopAPI (todo documentation)onTaskCompleted: a function which can be invoked with the task resultonTaskCanceled: a function which can be invoked to cancel the task- any other attributes assigned by previous tranform(s)
Servicesβ
Services connect the Octostar user interface with the transforms by the app.
From the example:
open_background_check:
role: context_menu
group: open
label: Credit Check
icon: fa-magnifying-glass-dollar
description: Opens the streamlit app passing the person as context for credit check
accepts:
- persons
- legal_person
transforms:
- enhance_item
- open_credit_check_iframe
Here we have a service open_background_check in the context_menu role (the default). The service appears under the open actions on the context menu, having the label Credit Check .
The service is available whenever the context (what was right clicked on) is accepted by any of the listed filters in the accepts section. Each name given in the accepts section must be either either:
-
- The name (key) of a filter defined in the
filterssection of the manifest
- The name (key) of a filter defined in the
- OR the name of a concept, eg
legal_personin the example (a shortcut semantic binding filter).
When the user select the operation, two transforms are performed in sequence. First the enhance_transform then the open_credit_check_iframe
Other roles (including record_viewer and set_viewer will become available soon).
The group attribute defines where the service appears in the context menu
-
- open
- edit
- transform
- general
- danger
The subgroup attribute may be included for transform services.
The optional show_progress parameter can be set to false (default is true ). When false the service progress bar is not displayed.
A params key can also be included on the service (not shown in the example) to include any additional parameters to be passed to the transform.
Another Full Example:
This example provides a transform service which uses the http example above to post the item to flask, then send the result from flask to the event emitter.
name: Send Folder To Flask
version: 1.0.0
description: Example posting from context menu to flask
filters:
is_a_folder:
type: semantically_bound
concepts:
- os_folder
transforms:
post_to_flask:
description: Upload the file to flask
type: http
method: POST
url: "{{ app.url }}/upload"
headers:
Content-Type: "application/json"
data: item
emit_notification:
description: Emit notification received from the flask app
type: emit_event
topic: octostar:desktop:builtins:showNotification
args: [ notification ]
services:
send_to_flask:
group: transform
subgroup: Folder
label: Post to Flask
icon: fa-car
description: Posts it to flask
accepts:
- is_a_folder
transforms:
- post_to_flask
- emit_notification