@hasna/computer 0.1.10 → 0.1.11
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.
- package/dist/cli/index.js +20 -14
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -7696,9 +7696,15 @@ function print(value, json, text) {
|
|
|
7696
7696
|
else
|
|
7697
7697
|
console.log(text);
|
|
7698
7698
|
}
|
|
7699
|
+
function hasJsonOption(options) {
|
|
7700
|
+
return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
|
|
7701
|
+
}
|
|
7702
|
+
function wantsJson(actionOptions, command) {
|
|
7703
|
+
return hasJsonOption(actionOptions) || hasJsonOption(command);
|
|
7704
|
+
}
|
|
7699
7705
|
function registerWebhookCommands(program2, options) {
|
|
7700
7706
|
const webhooks = program2.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
|
|
7701
|
-
webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions) => {
|
|
7707
|
+
webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
|
|
7702
7708
|
const timestamp = new Date().toISOString();
|
|
7703
7709
|
const channel = {
|
|
7704
7710
|
id: actionOptions.id,
|
|
@@ -7719,11 +7725,11 @@ function registerWebhookCommands(program2, options) {
|
|
|
7719
7725
|
throw new Error(`Transport ${actionOptions.transport} is reserved for future use and cannot be added yet`);
|
|
7720
7726
|
}
|
|
7721
7727
|
const saved = await createClient(options).addChannel(channel);
|
|
7722
|
-
print(sanitizeChannelForOutput(saved),
|
|
7728
|
+
print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
|
|
7723
7729
|
});
|
|
7724
|
-
webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
7730
|
+
webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
7725
7731
|
const channels = await createClient(options).listChannels();
|
|
7726
|
-
if (actionOptions
|
|
7732
|
+
if (wantsJson(actionOptions, command)) {
|
|
7727
7733
|
console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
|
|
7728
7734
|
return;
|
|
7729
7735
|
}
|
|
@@ -7735,11 +7741,11 @@ function registerWebhookCommands(program2, options) {
|
|
|
7735
7741
|
console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
|
|
7736
7742
|
}
|
|
7737
7743
|
});
|
|
7738
|
-
webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
|
|
7744
|
+
webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
7739
7745
|
const removed = await createClient(options).removeChannel(id);
|
|
7740
|
-
print({ removed },
|
|
7746
|
+
print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
|
|
7741
7747
|
});
|
|
7742
|
-
webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
|
|
7748
|
+
webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
7743
7749
|
const result = await createClient(options).testChannel(id, {
|
|
7744
7750
|
source: options.source,
|
|
7745
7751
|
type: actionOptions.type,
|
|
@@ -7747,13 +7753,13 @@ function registerWebhookCommands(program2, options) {
|
|
|
7747
7753
|
message: actionOptions.message,
|
|
7748
7754
|
data: parseJsonObject(actionOptions.data, { test: true })
|
|
7749
7755
|
});
|
|
7750
|
-
print(result,
|
|
7756
|
+
print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
|
|
7751
7757
|
});
|
|
7752
7758
|
return webhooks;
|
|
7753
7759
|
}
|
|
7754
7760
|
function registerEventCommands(program2, options) {
|
|
7755
7761
|
const events = program2.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
|
|
7756
|
-
events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions) => {
|
|
7762
|
+
events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions, command) => {
|
|
7757
7763
|
const result = await createClient(options).emit({
|
|
7758
7764
|
source: actionOptions.source ?? options.source,
|
|
7759
7765
|
type,
|
|
@@ -7764,9 +7770,9 @@ function registerEventCommands(program2, options) {
|
|
|
7764
7770
|
data: parseJsonObject(actionOptions.data, {}),
|
|
7765
7771
|
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
7766
7772
|
}, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
|
|
7767
|
-
print(result,
|
|
7773
|
+
print(result, wantsJson(actionOptions, command), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
|
|
7768
7774
|
});
|
|
7769
|
-
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
7775
|
+
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
7770
7776
|
let rows = await createClient(options).listEvents();
|
|
7771
7777
|
if (actionOptions.source)
|
|
7772
7778
|
rows = rows.filter((event) => event.source === actionOptions.source);
|
|
@@ -7774,7 +7780,7 @@ function registerEventCommands(program2, options) {
|
|
|
7774
7780
|
rows = rows.filter((event) => event.type === actionOptions.type);
|
|
7775
7781
|
if (actionOptions.limit)
|
|
7776
7782
|
rows = rows.slice(-actionOptions.limit);
|
|
7777
|
-
if (actionOptions
|
|
7783
|
+
if (wantsJson(actionOptions, command)) {
|
|
7778
7784
|
console.log(JSON.stringify(rows, null, 2));
|
|
7779
7785
|
return;
|
|
7780
7786
|
}
|
|
@@ -7785,14 +7791,14 @@ function registerEventCommands(program2, options) {
|
|
|
7785
7791
|
for (const event of rows)
|
|
7786
7792
|
console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
|
|
7787
7793
|
});
|
|
7788
|
-
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
7794
|
+
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
7789
7795
|
const result = await createClient(options).replay({
|
|
7790
7796
|
eventId: actionOptions.id,
|
|
7791
7797
|
source: actionOptions.source,
|
|
7792
7798
|
type: actionOptions.type,
|
|
7793
7799
|
dryRun: actionOptions.dryRun
|
|
7794
7800
|
});
|
|
7795
|
-
print(result,
|
|
7801
|
+
print(result, wantsJson(actionOptions, command), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
|
|
7796
7802
|
});
|
|
7797
7803
|
return events;
|
|
7798
7804
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/computer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Open-source computer use for AI agents — control your Mac with Anthropic or OpenAI. CLI + MCP server + REST API + Dashboard.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"license": "Apache-2.0",
|
|
75
75
|
"dependencies": {
|
|
76
76
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
77
|
-
"@hasna/events": "^0.1.
|
|
77
|
+
"@hasna/events": "^0.1.7",
|
|
78
78
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
79
79
|
"chalk": "^5.4.1",
|
|
80
80
|
"commander": "^13.1.0",
|