@harny/sdk 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/package.json +46 -40
  2. package/dist/cjs/agent/adapters.d.ts +0 -167
  3. package/dist/cjs/agent/adapters.js +0 -557
  4. package/dist/cjs/agent/adapters.js.map +0 -1
  5. package/dist/cjs/agent/hooks.d.ts +0 -52
  6. package/dist/cjs/agent/hooks.js +0 -41
  7. package/dist/cjs/agent/hooks.js.map +0 -1
  8. package/dist/cjs/agent/index.d.ts +0 -34
  9. package/dist/cjs/agent/index.js +0 -62
  10. package/dist/cjs/agent/index.js.map +0 -1
  11. package/dist/cjs/agent/loop.d.ts +0 -401
  12. package/dist/cjs/agent/loop.js +0 -1252
  13. package/dist/cjs/agent/loop.js.map +0 -1
  14. package/dist/cjs/agent/roster.d.ts +0 -62
  15. package/dist/cjs/agent/roster.js +0 -149
  16. package/dist/cjs/agent/roster.js.map +0 -1
  17. package/dist/cjs/agent/session.d.ts +0 -106
  18. package/dist/cjs/agent/session.js +0 -261
  19. package/dist/cjs/agent/session.js.map +0 -1
  20. package/dist/cjs/agent/spend.d.ts +0 -39
  21. package/dist/cjs/agent/spend.js +0 -70
  22. package/dist/cjs/agent/spend.js.map +0 -1
  23. package/dist/cjs/agent/tools.d.ts +0 -83
  24. package/dist/cjs/agent/tools.js +0 -212
  25. package/dist/cjs/agent/tools.js.map +0 -1
  26. package/dist/cjs/agent/tracing.d.ts +0 -72
  27. package/dist/cjs/agent/tracing.js +0 -128
  28. package/dist/cjs/agent/tracing.js.map +0 -1
  29. package/dist/cjs/agent/util.d.ts +0 -60
  30. package/dist/cjs/agent/util.js +0 -188
  31. package/dist/cjs/agent/util.js.map +0 -1
  32. package/dist/cjs/conflictQuestion.d.ts +0 -137
  33. package/dist/cjs/conflictQuestion.js +0 -356
  34. package/dist/cjs/conflictQuestion.js.map +0 -1
  35. package/dist/cjs/index.d.ts +0 -950
  36. package/dist/cjs/index.js +0 -1124
  37. package/dist/cjs/index.js.map +0 -1
  38. package/dist/cjs/memoryV1.d.ts +0 -121
  39. package/dist/cjs/memoryV1.js +0 -132
  40. package/dist/cjs/memoryV1.js.map +0 -1
  41. package/dist/cjs/package.json +0 -1
  42. package/dist/esm/agent/adapters.d.ts +0 -167
  43. package/dist/esm/agent/adapters.js +0 -543
  44. package/dist/esm/agent/adapters.js.map +0 -1
  45. package/dist/esm/agent/hooks.d.ts +0 -52
  46. package/dist/esm/agent/hooks.js +0 -36
  47. package/dist/esm/agent/hooks.js.map +0 -1
  48. package/dist/esm/agent/index.d.ts +0 -34
  49. package/dist/esm/agent/index.js +0 -28
  50. package/dist/esm/agent/index.js.map +0 -1
  51. package/dist/esm/agent/loop.d.ts +0 -401
  52. package/dist/esm/agent/loop.js +0 -1243
  53. package/dist/esm/agent/loop.js.map +0 -1
  54. package/dist/esm/agent/roster.d.ts +0 -62
  55. package/dist/esm/agent/roster.js +0 -143
  56. package/dist/esm/agent/roster.js.map +0 -1
  57. package/dist/esm/agent/session.d.ts +0 -106
  58. package/dist/esm/agent/session.js +0 -221
  59. package/dist/esm/agent/session.js.map +0 -1
  60. package/dist/esm/agent/spend.d.ts +0 -39
  61. package/dist/esm/agent/spend.js +0 -65
  62. package/dist/esm/agent/spend.js.map +0 -1
  63. package/dist/esm/agent/tools.d.ts +0 -83
  64. package/dist/esm/agent/tools.js +0 -205
  65. package/dist/esm/agent/tools.js.map +0 -1
  66. package/dist/esm/agent/tracing.d.ts +0 -72
  67. package/dist/esm/agent/tracing.js +0 -119
  68. package/dist/esm/agent/tracing.js.map +0 -1
  69. package/dist/esm/agent/util.d.ts +0 -60
  70. package/dist/esm/agent/util.js +0 -168
  71. package/dist/esm/agent/util.js.map +0 -1
  72. package/dist/esm/conflictQuestion.d.ts +0 -137
  73. package/dist/esm/conflictQuestion.js +0 -346
  74. package/dist/esm/conflictQuestion.js.map +0 -1
  75. package/dist/esm/index.d.ts +0 -950
  76. package/dist/esm/index.js +0 -1072
  77. package/dist/esm/index.js.map +0 -1
  78. package/dist/esm/memoryV1.d.ts +0 -121
  79. package/dist/esm/memoryV1.js +0 -124
  80. package/dist/esm/memoryV1.js.map +0 -1
  81. package/dist/esm/package.json +0 -1
@@ -1,60 +0,0 @@
1
- /**
2
- * Small helpers the agent modules share. Nothing here reaches the network.
3
- *
4
- * `pyDumps` writes JSON the way the Python SDK's agent does (", " and ": "
5
- * separators), so a tool result or a quoted title reads byte for byte the
6
- * same to the business's model whichever SDK runs the agent.
7
- */
8
- /** Hex SHA-256 of a UTF-8 string (WebCrypto, built into Node 20+). */
9
- export declare function sha256Hex(text: string): Promise<string>;
10
- export declare function toHex(bytes: Uint8Array): string;
11
- /** `bytes` random bytes as lowercase hex. */
12
- export declare function randomHex(bytes: number): string;
13
- /** A random 32-hex run id (a v4 UUID without dashes). */
14
- export declare function newRunId(): string;
15
- /** Text placed inside a <context>, <actions> or <email> wrapper cannot close it. */
16
- export declare function asData(text: string): string;
17
- export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
18
- /** Truthiness as the Python agent reads it: empty arrays and objects are false. */
19
- export declare function truthy(value: unknown): boolean;
20
- /** `value` if truthy, else `fallback`. */
21
- export declare function or<T>(value: unknown, fallback: T): unknown;
22
- /** Whole-number conversion that never throws (`0` for anything unreadable). */
23
- export declare function toInt(value: unknown): number;
24
- /** The first `limit` characters (code points) of `text`. */
25
- export declare function clipChars(text: string, limit: number): string;
26
- /**
27
- * JSON with the Python SDK's default separators. `undefined` is written as
28
- * `null`; a `Date` as its ISO string.
29
- */
30
- export declare function pyDumps(value: unknown, ensureAscii?: boolean): string;
31
- /** A string quoted the way the Python agent names it in a message ('x'). */
32
- export declare function quoted(text: string): string;
33
- /** A deep copy through JSON (what a tool call's arguments are made of). */
34
- export declare function plainCopy<T>(value: T): T;
35
- /** Node's hook for how `console.log` and `util.inspect` show an object. */
36
- export declare const INSPECT: unique symbol;
37
- /**
38
- * A date-time string as the Python SDK writes it after reading it
39
- * (`datetime.isoformat()`): `Z` becomes `+00:00`, fractions are six digits or
40
- * none. Anything that is not a date-time passes through unchanged.
41
- */
42
- export declare function pyIsoformat(value: unknown): unknown;
43
- /** The longest delay a timer can hold; a larger one would fire at once. */
44
- export declare const MAX_TIMER_MS = 2147483647;
45
- /** Resolve after `ms`, or reject at once when `signal` aborts. */
46
- export declare function sleep(ms: number, signal?: AbortSignal | null): Promise<void>;
47
- /**
48
- * The loop's clock: milliseconds on a steady clock, and a wait the run's
49
- * time can cut short. Tests replace these two; nothing else should.
50
- */
51
- export declare const clock: {
52
- now: () => number;
53
- sleep: (ms: number, signal?: AbortSignal | null) => Promise<void>;
54
- };
55
- /** Thrown inside a run that already stopped (its time ran out). Never reaches the caller. */
56
- export declare class RunAborted extends Error {
57
- constructor();
58
- }
59
- /** The process environment when there is one (Node), else an empty map. */
60
- export declare function processEnv(): Record<string, string | undefined>;
@@ -1,168 +0,0 @@
1
- /**
2
- * Small helpers the agent modules share. Nothing here reaches the network.
3
- *
4
- * `pyDumps` writes JSON the way the Python SDK's agent does (", " and ": "
5
- * separators), so a tool result or a quoted title reads byte for byte the
6
- * same to the business's model whichever SDK runs the agent.
7
- */
8
- /** Hex SHA-256 of a UTF-8 string (WebCrypto, built into Node 20+). */
9
- export async function sha256Hex(text) {
10
- const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
11
- return toHex(new Uint8Array(digest));
12
- }
13
- export function toHex(bytes) {
14
- return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
15
- }
16
- /** `bytes` random bytes as lowercase hex. */
17
- export function randomHex(bytes) {
18
- const buffer = new Uint8Array(bytes);
19
- globalThis.crypto.getRandomValues(buffer);
20
- return toHex(buffer);
21
- }
22
- /** A random 32-hex run id (a v4 UUID without dashes). */
23
- export function newRunId() {
24
- if (typeof globalThis.crypto?.randomUUID === "function") {
25
- return globalThis.crypto.randomUUID().replace(/-/g, "");
26
- }
27
- return randomHex(16);
28
- }
29
- /** Text placed inside a <context>, <actions> or <email> wrapper cannot close it. */
30
- export function asData(text) {
31
- return text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
32
- }
33
- export function isPlainObject(value) {
34
- return typeof value === "object" && value !== null && !Array.isArray(value);
35
- }
36
- /** Truthiness as the Python agent reads it: empty arrays and objects are false. */
37
- export function truthy(value) {
38
- if (value === null || value === undefined || value === false || value === 0 || value === "")
39
- return false;
40
- if (Array.isArray(value))
41
- return value.length > 0;
42
- if (isPlainObject(value))
43
- return Object.keys(value).length > 0;
44
- return true;
45
- }
46
- /** `value` if truthy, else `fallback`. */
47
- export function or(value, fallback) {
48
- return truthy(value) ? value : fallback;
49
- }
50
- /** Whole-number conversion that never throws (`0` for anything unreadable). */
51
- export function toInt(value) {
52
- const n = typeof value === "number" ? value : Number(value);
53
- return Number.isFinite(n) ? Math.trunc(n) : 0;
54
- }
55
- /** The first `limit` characters (code points) of `text`. */
56
- export function clipChars(text, limit) {
57
- const chars = Array.from(text);
58
- return chars.length <= limit ? text : chars.slice(0, limit).join("");
59
- }
60
- function jsonString(text, ensureAscii) {
61
- const out = JSON.stringify(text);
62
- if (!ensureAscii)
63
- return out;
64
- return out.replace(/[\u007f-￿]/g, (c) => "\\u" + c.charCodeAt(0).toString(16).padStart(4, "0"));
65
- }
66
- /**
67
- * JSON with the Python SDK's default separators. `undefined` is written as
68
- * `null`; a `Date` as its ISO string.
69
- */
70
- export function pyDumps(value, ensureAscii = false) {
71
- if (value === null || value === undefined)
72
- return "null";
73
- if (typeof value === "string")
74
- return jsonString(value, ensureAscii);
75
- if (typeof value === "boolean")
76
- return value ? "true" : "false";
77
- if (typeof value === "number") {
78
- if (Number.isNaN(value))
79
- return "NaN";
80
- if (!Number.isFinite(value))
81
- return value > 0 ? "Infinity" : "-Infinity";
82
- return String(value);
83
- }
84
- if (typeof value === "bigint")
85
- return value.toString();
86
- if (value instanceof Date)
87
- return jsonString(value.toISOString(), ensureAscii);
88
- if (Array.isArray(value))
89
- return "[" + value.map((v) => pyDumps(v, ensureAscii)).join(", ") + "]";
90
- if (typeof value === "object") {
91
- const parts = Object.entries(value).map(([k, v]) => `${jsonString(k, ensureAscii)}: ${pyDumps(v, ensureAscii)}`);
92
- return "{" + parts.join(", ") + "}";
93
- }
94
- return jsonString(String(value), ensureAscii);
95
- }
96
- /** A string quoted the way the Python agent names it in a message ('x'). */
97
- export function quoted(text) {
98
- return `'${text}'`;
99
- }
100
- /** A deep copy through JSON (what a tool call's arguments are made of). */
101
- export function plainCopy(value) {
102
- return JSON.parse(JSON.stringify(value ?? null));
103
- }
104
- /** Node's hook for how `console.log` and `util.inspect` show an object. */
105
- export const INSPECT = Symbol.for("nodejs.util.inspect.custom");
106
- const ISO_DATETIME = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2}:\d{2})(?:\.(\d+))?(Z|[+-]\d{2}:?\d{2})?$/;
107
- /**
108
- * A date-time string as the Python SDK writes it after reading it
109
- * (`datetime.isoformat()`): `Z` becomes `+00:00`, fractions are six digits or
110
- * none. Anything that is not a date-time passes through unchanged.
111
- */
112
- export function pyIsoformat(value) {
113
- if (typeof value !== "string")
114
- return value;
115
- const match = ISO_DATETIME.exec(value.trim());
116
- if (!match)
117
- return value;
118
- let fraction = match[3] ? (match[3] + "000000").slice(0, 6) : "";
119
- if (/^0*$/.test(fraction))
120
- fraction = "";
121
- let zone = match[4] ?? "";
122
- if (zone === "Z" || zone === "-00:00" || zone === "-0000")
123
- zone = "+00:00";
124
- else if (zone && !zone.includes(":"))
125
- zone = `${zone.slice(0, 3)}:${zone.slice(3)}`;
126
- return `${match[1]}T${match[2]}${fraction ? "." + fraction : ""}${zone}`;
127
- }
128
- /** The longest delay a timer can hold; a larger one would fire at once. */
129
- export const MAX_TIMER_MS = 2147483647;
130
- /** Resolve after `ms`, or reject at once when `signal` aborts. */
131
- export function sleep(ms, signal) {
132
- return new Promise((resolve, reject) => {
133
- if (signal?.aborted) {
134
- reject(new RunAborted());
135
- return;
136
- }
137
- const timer = setTimeout(() => {
138
- signal?.removeEventListener("abort", onAbort);
139
- resolve();
140
- }, Math.min(ms, MAX_TIMER_MS));
141
- const onAbort = () => {
142
- clearTimeout(timer);
143
- reject(new RunAborted());
144
- };
145
- signal?.addEventListener("abort", onAbort, { once: true });
146
- });
147
- }
148
- /**
149
- * The loop's clock: milliseconds on a steady clock, and a wait the run's
150
- * time can cut short. Tests replace these two; nothing else should.
151
- */
152
- export const clock = {
153
- now: () => (typeof globalThis.performance?.now === "function" ? globalThis.performance.now() : Date.now()),
154
- sleep: (ms, signal) => sleep(ms, signal),
155
- };
156
- /** Thrown inside a run that already stopped (its time ran out). Never reaches the caller. */
157
- export class RunAborted extends Error {
158
- constructor() {
159
- super("the run stopped");
160
- this.name = "RunAborted";
161
- }
162
- }
163
- /** The process environment when there is one (Node), else an empty map. */
164
- export function processEnv() {
165
- const proc = globalThis.process;
166
- return proc?.env ?? {};
167
- }
168
- //# sourceMappingURL=util.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/agent/util.ts"],"names":[],"mappings":"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"}
@@ -1,137 +0,0 @@
1
- /**
2
- * What to ask a person whose notes conflict, and the rule for when. Pure: no network, no model call, no clock.
3
- *
4
- * A person can say two things that cannot both be true ("Maya prefers email", weeks later "Maya prefers phone").
5
- * Harny keeps both and picks neither; the context response returns them in
6
- * `conflicts`. Harny adds no pause of its own. The question is YOUR confirm step's: call
7
- * `decideConflictQuestion` before an action, show `text` if it says `ask`, tell Harny you asked
8
- * (`client.markConflictAsked`), and send the person's answer (`client.answerConflict`). The answer is saved as
9
- * something the person said, and the conflict stops being returned.
10
- *
11
- * const result = await client.assembleContext("send Maya the update", undefined, { user });
12
- * const decision = decideConflictQuestion({
13
- * conflicts: result.conflicts,
14
- * dependsOn: conflictsTheSendDependsOn.map((c) => c.record_id_1), // the ones whose answer changes what is sent
15
- * actionKinds: ["others_affected"], // the kinds of action this is
16
- * mode: result.conflict_question_mode, // the app's "When notes conflict" setting
17
- * phrases: new QuestionPhrases({ action: "send", question: "Does Maya prefer email or phone?" }),
18
- * });
19
- * if (decision.ask) {
20
- * const claim = await client.markConflictAsked(decision, { user }); // claim the question FIRST
21
- * if (claim.first_time) show(decision.text); // only the first claim shows it
22
- * // (in your own confirm card or chat)
23
- * }
24
- *
25
- * Report before you show, and show only when `first_time` is true: the first report wins, so a second action in the same
26
- * turn, a retry or a second process cannot put the question twice. (A decision by itself changes nothing: `ledger` and
27
- * `record` only help a host that keeps its own memory.)
28
- *
29
- * THE RULE (all six must hold, checked in this order; the first that fails names itself in `reason`):
30
- *
31
- * 1. the action is of the "others affected" or "irreversible" kind (`ASKING_KINDS`): an action that only touches
32
- * the person's own things never asks;
33
- * 2. a conflict exists for a note the action depends on. `dependsOn` lists the `record_id_1` / `record_id_2` of each
34
- * conflict whose answer changes what the action does; you (or your agent) decide that from the two statements;
35
- * 3. the question is on (`mode` is not null or undefined). The response names the app's mode only while Harny has
36
- * the question on, so no mode with a conflict in hand means do not ask;
37
- * 4. the person did not say both in one conversation (`same_conversation` is false): they have just said it, so
38
- * they are never asked about it there;
39
- * 5. that conflict has not been asked about before: at most once per conflict. It counts as asked when the
40
- * response marked it `asked` or your `ledger` has it;
41
- * 6. the wording the question needs was supplied FOR THAT CONFLICT (a lone `QuestionPhrases` is accepted only while
42
- * one conflict can be asked; with several, pass a function of the conflict or a map by `conflictKey`).
43
- *
44
- * THE WORDS depend on the app's "When notes conflict" setting: `simple` (the default, no dates), `precise` (both
45
- * statements with the day each was said) and `handoff` (a short question that offers the detail, which your own
46
- * interface shows from the `conflicts` data). The sentences carry natural-language phrases ("Maya prefers email") that the stored statements do not, so YOU supply them in `QuestionPhrases`; this module never writes
47
- * wording of its own: a missing phrase is a `missing_phrases` refusal, not a guess.
48
- */
49
- /** The closed set the app's "When notes conflict" setting takes. */
50
- export declare const CONFLICT_QUESTION_MODES: readonly ["simple", "precise", "handoff"];
51
- export type ConflictQuestionMode = (typeof CONFLICT_QUESTION_MODES)[number];
52
- export declare const DEFAULT_CONFLICT_QUESTION_MODE: ConflictQuestionMode;
53
- /** The action kinds that may ask. `money` and `nobody_else` do not. */
54
- export declare const ASKING_KINDS: ReadonlySet<string>;
55
- /** One conflict as the context response carries it (a typed item or a plain object). */
56
- export type ConflictLike = Record<string, any>;
57
- export interface QuestionPhrasesInit {
58
- action?: string;
59
- question?: string;
60
- claim_1?: string;
61
- claim_2?: string;
62
- topic?: string;
63
- }
64
- /**
65
- * The natural-language pieces YOU write about THIS conflict.
66
- *
67
- * `action`: the verb of what is about to happen ("send", "reply", "share"); all three modes. `question`: a complete
68
- * yes/no question about the fact, for `simple` ("Does Maya prefer email or phone?"). `claim_1` /
69
- * `claim_2`: the two statements as they read after "you said" and "that", for `precise` ("Maya prefers email", "she prefers phone"). `topic`: what the notes conflict about, for `handoff` ("Maya's contact preference").
70
- */
71
- export declare class QuestionPhrases {
72
- readonly action: string;
73
- readonly question: string;
74
- readonly claim_1: string;
75
- readonly claim_2: string;
76
- readonly topic: string;
77
- constructor(init?: QuestionPhrasesInit);
78
- }
79
- /**
80
- * The words for the conflict being asked about: one `QuestionPhrases` (only while a single conflict can be asked),
81
- * a function of the conflict item, or a map from `conflictKey` (a `Map` or a plain object).
82
- */
83
- export type PhrasesSource = QuestionPhrases | QuestionPhrasesInit | ((conflict: ConflictLike) => QuestionPhrases | null | undefined) | ReadonlyMap<string, QuestionPhrases> | Readonly<Record<string, QuestionPhrases>>;
84
- /** Where YOUR app remembers which conflicts it has asked about, besides Harny's own memory. Optional. */
85
- export interface ConflictAskLedger {
86
- has(key: string): boolean;
87
- add(key: string): void;
88
- }
89
- /** A ledger held in memory: for tests and for a first draft. */
90
- export declare class InMemoryConflictAskLedger implements ConflictAskLedger {
91
- private readonly asked;
92
- constructor(asked?: Iterable<string>);
93
- has(key: string): boolean;
94
- add(key: string): void;
95
- get size(): number;
96
- }
97
- /**
98
- * The decision: `ask` and, when true, the `text` to put to the person. `reason` is `asked` or the first rule that
99
- * failed: `kind_not_eligible`, `no_conflict`, `rule_dark`, `same_conversation`, `already_asked`,
100
- * `ambiguous_phrases` (one `QuestionPhrases` offered while several conflicts could be asked), `missing_phrases`.
101
- * `key` / `conflict` name the conflict asked about (or, for a refusal that found one, the one it stopped on); pass
102
- * the decision itself, or `conflict`, to `markConflictAsked`.
103
- */
104
- export interface ConflictQuestion {
105
- ask: boolean;
106
- reason: string;
107
- text: string | null;
108
- key: string | null;
109
- conflict: ConflictLike | null;
110
- }
111
- export interface DecideConflictQuestionOptions {
112
- /** `result.conflicts` of the context response. */
113
- conflicts: ReadonlyArray<ConflictLike> | null | undefined;
114
- /** The record ids of the conflicts the action's result depends on. */
115
- dependsOn: Iterable<string> | string;
116
- /** The kinds of action this is. */
117
- actionKinds: Iterable<string> | string;
118
- /** `result.conflict_question_mode`. No mode (null or undefined) means the question is off: do not ask. */
119
- mode: string | null | undefined;
120
- phrases: PhrasesSource;
121
- ledger?: ConflictAskLedger;
122
- /** Add the conflict to `ledger` when this returns an ask. */
123
- record?: boolean;
124
- }
125
- /** One of `CONFLICT_QUESTION_MODES`; anything else is the default (the plain, no-dates question). */
126
- export declare function normaliseMode(value: unknown): ConflictQuestionMode;
127
- /** `2024-09-22` -> `Sept 22`. An empty string when the value is not an ISO day. */
128
- export declare function formatDay(isoDay: unknown): string;
129
- /** The question for `mode`. Throws on a missing phrase or an unreadable said-day (`precise` only). */
130
- export declare function questionText(mode: unknown, conflict: ConflictLike, phrases: QuestionPhrases): string;
131
- /**
132
- * The identity of one conflict: the two stored notes behind it, in either order. The same value Harny puts in
133
- * `conflicts[].conflict_key`, stable across responses, so "asked once" holds however the list is ordered.
134
- */
135
- export declare function conflictKey(conflict: ConflictLike): string;
136
- /** Whether to ask now, and what to say. See the module comment for the rule. */
137
- export declare function decideConflictQuestion(options: DecideConflictQuestionOptions): ConflictQuestion;