		       Cluepacket Documentation

Nat Friedman <nat@nat.org>
Last updated: Fri Jul  6 01:16:18 2003

Introduction
------------

This file documents the format of a cluepacket.  

Before reading this file, please go through summary.txt, which
explains the general design of the dashboard and takes very little
time to read.  That file is here:

    http://cvs.gnome.org/lxr/source/dashboard/doc/summary.txt

A cluepacket is what a frontend application (whatever app the user is
interacting with at a given time) sends to the dashboard whenever the
user begins interacting with some kind of object (mail, web page,
spreadsheet), or whenever the active object changes.

Overview
--------

A cluepacket is a little XML block sent by a frontend application (web
browser, email client, editor) to the dashboard.  The cluepacket is
sent over TCP to port 5913 on localhost.  See dashboard-frontend.c
for some sample code that does this:

    http://cvs.gnome.org/lxr/source/dashboard/frontends/dashboard-frontend.c

Form of a Cluepacket
--------------------

A cluepacket is made up of a set of "clues" and a small amount of
information about the identity and state of the application sending
the cluepacket.

Here is an example cluepacket:

    <CluePacket>
        <Frontend>Epiphany</Frontend>
        <Context>Tab 1</Context>
        <Focused>True</Focused>
	<Additive>False</Additive>

        <Clue Type="url" Relevance="10">
            http://www.nat.org/dashboard
        </Clue>

        <Clue Type="htmlblock" Relevance="10">
            ... full html of page ...
        </Clue>
    </CluePacket>

This cluepacket might be sent by the Epiphany web browser to the
dashboard when the user visits the dashboard blog in tab 1 of his
browser.

Clues
-----

* Definition

A clue is a single piece of information that partially describes the
user-interactable object in the frontend application.  The dashboard
uses the clues to try to find objects that the user is not interacting
with which might be relevant to what he's doing.

* Non-additivity

Taken together, the clues in a single cluepacket should offer as
complete as possible a representation of all the interesting data
about the object being described.

That is, if you want to send clues to the dashboard about a mail the
user is reading, you should bundle all the relevant clues -- sender,
subject, to, cc, body -- into a single cluepacket.  Do not send them
as separate cluepackets.

When the dashboard receives a new cluepacket about an object, it
forgets everything it knew about that object before (modulo some
caching for performance).

* Types

The Clue.Type property is a hint which the Dashboard's indexing and
querying backends can use to try to improve the quality of the matches
they generate.  It is not necessary to specify the type for your clue,
but it may be helpful.

There is no limit to the number of types that you can use; you are
free to invent your own, but of course they will only be effective if
the backends recognize them.  We have created a list of standard clue
types that frontends can apply to clues and that backends can use to
improve their matching.  Examples include: email, url, date,
textblock.  Please see cluetypes.txt for the canonical list:

    http://cvs.gnome.org/lxr/source/dashboard/doc/cluetypes.txt

If no type is specified, the backends will treat the clue as a block
of text (the "textblock" clue type specifies this explicitly).

* Relevance

Frontends frequently have an idea of how relevant a clue is to the
object being described, and this information can help the Dashboard
only display the best matches.

For example, the From address on an email is usually more important
for generating relevant matches than an address on the Cc line.

As another example, the Gaim frontend sends the last 20 lines of an IM
conversation to the dashboard, but they are chunked so that as the
lines get older, their relevance declines.

Relevance is a number from 1 to 10.  If Relevance is not specified,
the dashboard assumes it is 10.

Frontend Information
--------------------

The cluepacket contains some identifying information about the
frontend application that's sending it so that the dashboard can
distinguish between cluepacket sent from various applications.

* Frontend

The frontend tag specifies the name of the application that's sending
the cluepacket.  This should be specific enough to be useful for
debugging, and also in case someone wanted to write a backend that did
some interesting processing of the cluepacket logs.

Here are some examples:

    <Frontend>Epiphany</Frontend>
    <Frontend>Gaim</Frontend>
    <Frontend>Evolution Mail</Frontend>
    <Frontend>Evolution Calendar</Frontend>
    <Frontend>Emacs</Frontend>
    <Frontend>Joe's Shell Script</Frontend>

You get the idea.

* Focused

The focused tag tells the dashboard whether or not the object being
described has focus in your windowing system.  Objects that don't have
focus because they are obscured, iconified or not selected should set
Focused to false.

This is critical information for the dashboard to have so that it
doesn't repopulate the matchlist with matches that aren't relevant to
whatever the user is doing at the time.

There is also a focus-changed cluepacket that frontends can send when
their focus changes, even if the active object does not change.  This
is described below; keep reading.

The Focused tag is required.  If it is not found in a CluePacket, the
Dashboard will discard that packet.

* Context

Some frontend applications can have multiple user-interactable objects
displayed at one time, though the user only interacts with one at a
time.

Gaim is a good example of this; it is a single application which can
have multiple IM conversation windows up at once.  Cluepackets
relevant to one conversation are probably not relevant to another
conversation.  There are other examples too: your web browser can have
tabs, your mailer can have separate windows, etc.

Context is an opaque string which you use to represent the user's
current interaction context.  Here's an example:

    <CluePacket>
        <Frontend>Gaim</Frontend>
        <Context>Conversation with SeanEgn</Context>
        <Focused>True</Focused>

        <Clue Type="aim" Relevance="10">SeanEgn</Clue>

        <Clue Type="textblock" Relevance="8">
            Hey Sean, how's it going?
            Not bad, busy with school.
        </Clue>

        <Clue Type="textblock" Relevance="10">
            School - fun.  Hey can you give me a hand with this
            plugin I'm writing?
        </Clue>

    </CluePacket>

This is a pretty good example because the specified Context is also
descriptive.  Now, if the user were to click on another IM window --
say, "Conversation with NatFriedman" -- then the dashboard would know
that the newly active frontend context has nothing to do with the
cluepacket above.

The Context doesn't have to be descriptive, it just has to be unique
between user Contexts.  An example of an opaque context might be:

    <CluePacket>
        <Frontend>Emacs</Frontend>
        <Context>WINDOWID-0x2c000d8</Context>
        <Focused>TRUE</Focused>

        ... CLUES GO HERE ...

    </CluePacket>

You can put whatever you want in Context as long as it uniquely
identifies the context.  The Context tag is optional but highly
preferred.  If the Context tag is omitted, the Dashboard will assume a
global context within that Frontend.

* Additive

Normally a new CluePacket signifies a context switch of sorts, usually
resulting from a change in focus of a frontend.  Under certain
circumstances, though, you want a new incoming CluePacket to augment
the currently displayed matches of the most recent CluePacket.  For
those, you want to set the Additive tag.

A good example of this is the accessibility frontend, which creates
CluePackets containing text that you've recently typed.  You obviously
don't want your existing matches to be removed as you type, but you do
want to see additional matches related to what you're typing at the time.

Focus-In Cluepackets
--------------------

The dashboard needs to know when an interaction context with an
interesting object gains focus, so that it can display matches
relevant to the new object, instead of leaving stale matches around.

So, basically, when your window gets focus, you can send a cluepacket
to the dashboard that just contains:

    <CluePacket>
        <Frontend>Epiphany</Frontend>
        <Context>Tab 1</Context>
        <Focused>True</Focused>
    </CluePacket>

The dashboard will remember the clues that you gave it before, while
the window was unfocused, so you don't need to resend them.  This can
make implementing frontends easier.

Of course, you don't have to send focus-only cluepackets; you can
build a full cluepacket and send it to the dashboard whenever you get
focus, too.  There's no need to send a focus-out cluepacket.

Syntax
------

The dashboard performs some basic XML validation on the cluepacket
before processing it.  If validator fails, the cluepacket is thrown
away.

You should make sure your frontend does the following things:

    - All attributes should be quoted.  So this is legal:

        <Clue Type=\"aim_name\" Relevance=\"10\">natfriedman</Clue>

      and this is not:

        <Clue Type=\"aim_name\" Relevance=10>natfriedman</Clue>

    - Tags and attributes must be capitalized.  Not only does this
      look really cool, it seems to help Mono's XML Serializer.

    - All node content must be escaped.

If you use one of the frontend libraries or modules, none of this
should be a problem for you.

Please see the DTD for a more rigorous syntax definition:

    http://cvs.gnome.org/lxr/source/dashboard/doc/cluepacket.dtd

Implementation
--------------

Cluepackets are designed to be easy to build and send.  To make it
even easier, the dashboard ships with helper code, libaries and
modules that help you construct and send cluepackets.  You can also
use some of the existing frontend code as examples.  

Check out the frontends/ directory for more information:

    http://cvs.gnome.org/lxr/source/dashboard/frontends/

If you're writing in C, I recommend reading the Evolution mail patch
for a particularly gorgeous example ;-).

