Masu.Issho (Masu v0.7.0)

Copy Markdown View Source

Masu's grids in Issho's rooms: agents read and change a grid as a person does, and the people who have it open see where they are and what they change.

A grid is named as a document is, "room/grid" ("notebook:42/tasks"): its issho :document, whose room is the part before the first "/". A place in a grid is Masu.Issho.Place. Its rows stay the grid's own: its source reads them, and its writes save them, the grid's way (Masu.Sheet). Issho carries who is there and where.

The grids an agent may use

Your app says which grid a name is, for whom, with a function of the name and the agent's Issho.Tool.Context, which gives the grid's attributes (those of data_grid/1, and scope, for its writes):

config :masu, Masu.Issho, grids: {MyApp.Grids, :for_agent}

def for_agent("project:" <> rest, ctx) do
  [project_id, "tasks"] = String.split(rest, "/")
  scope = MyApp.Accounts.scope_for(ctx.opts[:on_behalf_of])
  {:ok, Keyword.put(tasks(scope, project_id), :scope, scope)}
end

def for_agent(_grid, _ctx), do: {:error, "There is no such grid."}

The agent is in the room (the room's policy lets it join), and each write asks the policy too (:write), before the grid's own rules.

Tools

tools/0: read a grid (in an order, filtered, searched), point at cells, edit cells, add rows and delete rows. Give them to an agent with Issho's (Issho.Tools.room/0), over MCP (Issho.MCP) or your app's own model (Issho.Tools).

config :masu, Masu.Issho, pace: 120, travel: true: pace, the milliseconds an agent stays on each cell it edits, typing, so the people see it (0 for none); travel, whether it goes to each cell and selects ranges as a drag does, as a person would (false: it is there at once). Only where it goes is sent: each browser draws the way there.

An agent that a person paused or stopped (Issho.Work) changes the grid no more: select_cells, edit_cells, add_rows and delete_rows say who paused it and what to do, as Issho's tools do; read_grid still reads. An edit of many cells, one by one, stops at the cell it is on.

Comments

Issho's comments (Issho.Components.comments/1) go on a cell or a range of a grid as on any place, and their marks are drawn on the cells. label/2 says such a place in words, for the :place slot.

Summary

Functions

A place of a grid in words, for people: "City of Acme" for a cell, "Name to City of Acme" for a range in a row, "City of 3 rows" for a range of rows. nil for no place, or a place of another grid, so that the words of whoever asks stay theirs. For the :place slot of Issho's comments

The place of a cell, or of a range of rows and keys, in a grid of a room.

Masu's tools for agents.

Functions

label(place, opts \\ [])

@spec label(map() | nil, keyword()) :: String.t() | nil

A place of a grid in words, for people: "City of Acme" for a cell, "Name to City of Acme" for a range in a row, "City of 3 rows" for a range of rows. nil for no place, or a place of another grid, so that the words of whoever asks stay theirs. For the :place slot of Issho's comments:

<.comments id="comments" room="orders:42">
  <:place :let={%{place: place, default: default}}>
    {Masu.Issho.label(place, grid: "orders:42/orders", columns: @labels, row: &order_name/1) ||
      default}
  </:place>
</.comments>

A place is in the grid's terms (Masu.Issho.Place), not a row's number, as each person has their own order: name a row by its content.

Options:

  • :grid, the grid's document: a place of another document gives nil. Any grid's place, without it.
  • :columns, the columns' labels by key, as a map or a list of pairs (%{"city" => "City"}); a key that is not there is itself.
  • :row, a function of a row's id that gives its name ("Acme"), or nil for "row 7".

place(grid, arg)

@spec place(String.t(), {term(), String.t()} | {[term()], [String.t()]}) :: map()

The place of a cell, or of a range of rows and keys, in a grid of a room.

tools()

@spec tools() :: [module()]

Masu's tools for agents.