mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-10-01 20:33:50 +00:00
Ship OpenFleet contracts and the OpenWall draft proposal (#177)
* feat: add OpenFleet membership and CoinPay rental contracts * Propose OpenWall broadcasts and direct messaging contracts * release: prepare OpenFleet and OpenWall public contracts * fix: use tested npm for compatible CLI installs
This commit is contained in:
parent
a333726a1e
commit
45c7629953
35 changed files with 2021 additions and 12 deletions
34
packages/sdk/README.md
Normal file
34
packages/sdk/README.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# @logicsrc/sdk
|
||||
|
||||
LogicSRC contract types and constructors for tasks, AgentSwarm sessions and
|
||||
OpenFleet descriptors. These helpers construct documents; they do not start
|
||||
agents, resolve remote identities or initiate payments.
|
||||
|
||||
```sh
|
||||
npm install @logicsrc/sdk @logicsrc/validators
|
||||
```
|
||||
|
||||
```ts
|
||||
import { createOpenFleet } from "@logicsrc/sdk";
|
||||
import { validate } from "@logicsrc/validators";
|
||||
|
||||
const fleet = createOpenFleet({
|
||||
id: "https://example.com/fleets/research",
|
||||
name: "Research",
|
||||
owner_did: "operator.coinpay",
|
||||
members: [{
|
||||
kind: "openagent",
|
||||
id: "analyst.coinpay",
|
||||
url: "https://example.com/agents/analyst.json"
|
||||
}]
|
||||
});
|
||||
|
||||
const result = validate("openfleet", fleet);
|
||||
if (!result.ok) throw new Error(JSON.stringify(result.errors));
|
||||
```
|
||||
|
||||
Use `@logicsrc/validators` 0.1.1 or newer for OpenFleet validation. See the
|
||||
[OpenFleet specification](https://logicsrc.com/docs/openfleet) for member
|
||||
bindings, exact decimal rental rates and CoinPay settlement metadata.
|
||||
|
||||
MIT © Profullstack, Inc.
|
||||
|
|
@ -11,5 +11,19 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"vitest": "^4.0.8"
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/profullstack/logicsrc.git",
|
||||
"directory": "packages/sdk"
|
||||
},
|
||||
"homepage": "https://github.com/profullstack/logicsrc/tree/master/packages/sdk",
|
||||
"files": [
|
||||
"dist",
|
||||
"!dist/*.test.*"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
export { createOpenFleet } from "./openfleet.js";
|
||||
export type {
|
||||
OpenFleet, OpenFleetJsonValue, OpenFleetMember, OpenFleetMemberReference,
|
||||
OpenFleetRental, OpenFleetRentalScope
|
||||
} from "./openfleet.js";
|
||||
|
||||
export type LogicSrcId = string;
|
||||
|
||||
export interface LogicSrcTask {
|
||||
|
|
|
|||
35
packages/sdk/src/openfleet.test.ts
Normal file
35
packages/sdk/src/openfleet.test.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { createOpenFleet, type OpenFleetMember } from "./index.js";
|
||||
|
||||
const members: OpenFleetMember[] = [
|
||||
{ kind: "openagent", id: "analyst.coinpay", url: "https://example.com/agent.json" },
|
||||
{ kind: "openswarm", id: `ed25519:${"a".repeat(64)}`, url: "https://example.com/manifest.json" }
|
||||
];
|
||||
|
||||
describe("createOpenFleet", () => {
|
||||
it.each([members.slice(0, 1), members.slice(1), members])("constructs single-kind and mixed fleets", (...fleetMembers) => {
|
||||
const fleet = createOpenFleet({
|
||||
id: "https://example.com/fleets/research", name: "Research", owner_did: "operator.coinpay",
|
||||
members: fleetMembers
|
||||
});
|
||||
expect(fleet.type).toBe("logicsrc.openfleet");
|
||||
expect(fleet.version).toBe("0.1");
|
||||
expect(fleet.members).toEqual(fleetMembers);
|
||||
expect(fleet.rentals).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps rental amounts as decimal strings and preserves metadata", () => {
|
||||
const input: Parameters<typeof createOpenFleet>[0] = {
|
||||
id: "https://example.com/fleets/research", name: "Research", owner_did: "operator.coinpay", members,
|
||||
metadata: { support: { languages: ["en", "fr"] } },
|
||||
rentals: [{
|
||||
id: "hourly", scope: { kind: "fleet" },
|
||||
rate: { amount: "9007199254740993.123456", currency: "USD", unit: "hour" },
|
||||
payment: { provider: "coinpay", payee_did: "operator.coinpay", checkout_url: "https://example.com/rent" }
|
||||
}]
|
||||
};
|
||||
const snapshot = structuredClone(input);
|
||||
expect(createOpenFleet(input)).toEqual({ ...input, type: "logicsrc.openfleet", version: "0.1" });
|
||||
expect(input).toEqual(snapshot);
|
||||
});
|
||||
});
|
||||
71
packages/sdk/src/openfleet.ts
Normal file
71
packages/sdk/src/openfleet.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
export type OpenFleetJsonValue =
|
||||
| null | boolean | number | string
|
||||
| OpenFleetJsonValue[] | { [key: string]: OpenFleetJsonValue };
|
||||
|
||||
/** OpenAgent binds to a logicsrc.agent DID; OpenSwarm binds to a file key. */
|
||||
export type OpenFleetMemberReference =
|
||||
| { kind: "openagent"; id: string }
|
||||
| { kind: "openswarm"; id: `ed25519:${string}` };
|
||||
|
||||
export type OpenFleetMember = OpenFleetMemberReference & {
|
||||
/** HTTPS URL of the agent profile or the signed ipfile manifest. */
|
||||
url: string;
|
||||
name?: string;
|
||||
role?: string;
|
||||
metadata?: Record<string, OpenFleetJsonValue>;
|
||||
};
|
||||
|
||||
export type OpenFleetRentalScope =
|
||||
| { kind: "fleet" }
|
||||
| { kind: "members"; members: OpenFleetMemberReference[] };
|
||||
|
||||
export interface OpenFleetRental {
|
||||
id: string;
|
||||
name?: string;
|
||||
scope: OpenFleetRentalScope;
|
||||
rate: {
|
||||
/** Exact non-negative USD decimal string, with six fractional digits. */
|
||||
amount: string;
|
||||
currency: "USD";
|
||||
/** Whole billing units; a month is 30 days, a task an agreed deliverable. */
|
||||
unit: "hour" | "day" | "month" | "task";
|
||||
};
|
||||
minimum_units?: number;
|
||||
maximum_units?: number;
|
||||
valid_from?: string;
|
||||
valid_until?: string;
|
||||
terms_url?: string;
|
||||
payment: {
|
||||
provider: "coinpay";
|
||||
payee_did: string;
|
||||
/** Merchant-published HTTPS checkout entry point; no fixed CoinPay API. */
|
||||
checkout_url: string;
|
||||
};
|
||||
metadata?: Record<string, OpenFleetJsonValue>;
|
||||
}
|
||||
|
||||
export interface OpenFleet {
|
||||
type: "logicsrc.openfleet";
|
||||
version: "0.1";
|
||||
/** Stable HTTPS fleet identifier, unique at its publisher's origin. */
|
||||
id: string;
|
||||
name: string;
|
||||
owner_did: string;
|
||||
description?: string;
|
||||
updated_at?: string;
|
||||
availability?: "available" | "busy" | "offline" | "unknown";
|
||||
tags?: string[];
|
||||
capabilities?: string[];
|
||||
metadata?: Record<string, OpenFleetJsonValue>;
|
||||
members: OpenFleetMember[];
|
||||
rentals?: OpenFleetRental[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a descriptor without fetching members or initiating payments.
|
||||
* Use validate("openfleet", document) from @logicsrc/validators before use:
|
||||
* TypeScript alone cannot check DID/key formats or rental references.
|
||||
*/
|
||||
export function createOpenFleet(input: Omit<OpenFleet, "type" | "version">): OpenFleet {
|
||||
return { ...input, type: "logicsrc.openfleet", version: "0.1" };
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue