Analyze Image
One script reply has been approved by the moderators Verified

Creates an image analysis task via the Nextcloud OCS Task Processing API and gives the completed result

Created by nextcloud 12 days ago Picked 5 times
Submitted by nextcloud Bun
Verified 12 days ago
1
import createClient, { type Middleware } from "openapi-fetch";
2

3
const TASK_TYPE_ANALYZE_IMAGES = "core:analyze-images";
4
const POLL_INTERVAL_MS = 1000;
5
const DEFAULT_POLL_TIMEOUT_MS = 600_000; // 10 minutes (ensure one cron job finished)
6

7
/**
8
 * Creates an image analysis task via the Nextcloud OCS Task Processing API,
9
 * polls until the task completes, and returns the analysis text.
10
 */
11
export async function main(
12
  ncResource: RT.Nextcloud,
13
  prompt: string,
14
  imageFileIds: number | string | Array<number | string>,
15
  model: string | null = null,
16
  timeout_ms: number = DEFAULT_POLL_TIMEOUT_MS,
17
  interval_ms: number = POLL_INTERVAL_MS,
18
) {
19
  if (timeout_ms < 1) {
20
    timeout_ms = DEFAULT_POLL_TIMEOUT_MS;
21
  }
22
  if (interval_ms < 1) {
23
    interval_ms = POLL_INTERVAL_MS;
24
  }
25
  if (!Array.isArray(imageFileIds)) {
26
    imageFileIds = [imageFileIds];
27
  }
28
  if (imageFileIds.length < 1) {
29
    throw new Error("imageFileIds must be a non-empty array of Nextcloud file IDs");
30
  }
31

32
  const client = createClient({ baseUrl: ncResource.baseUrl }) as any;
33
  const authMiddleware: Middleware = {
34
    async onRequest({ request }) {
35
      request.headers.set(
36
        "Authorization",
37
        `Basic ${btoa(ncResource.userId + ":" + ncResource.token)}`,
38
      );
39
      return request;
40
    },
41
  };
42
  client.use(authMiddleware);
43

44
  // Schedule the image analysis task
45
  const { data: scheduleData, error: scheduleError } = await client.POST(
46
    "/ocs/v2.php/taskprocessing/schedule",
47
    {
48
      params: {
49
        header: {
50
          "OCS-APIRequest": true,
51
        },
52
        query: {
53
          format: "json",
54
        },
55
      },
56
      body: {
57
        type: TASK_TYPE_ANALYZE_IMAGES,
58
        input: {
59
          model: model,
60
          input: prompt,
61
          images: imageFileIds,
62
        },
63
        appId: "windmill",
64
      },
65
    },
66
  );
67

68
  if (scheduleError) {
69
    throw new Error(
70
      `Failed to schedule image analysis task: ${JSON.stringify(scheduleError)}`,
71
    );
72
  }
73
  const taskId = scheduleData?.ocs?.data?.task?.id;
74

75
  // Polls every interval until timeout or a result happens
76
  const deadline = Date.now() + timeout_ms;
77
  while (Date.now() < deadline) {
78
    console.log("Polling task output");
79
    const { data: taskData, error: taskError } = await client.GET(
80
      "/ocs/v2.php/taskprocessing/task/{id}",
81
      {
82
        params: {
83
          header: {
84
            "OCS-APIRequest": true,
85
          },
86
          query: {
87
            format: "json",
88
          },
89
          path: {
90
            id: taskId,
91
          },
92
        },
93
      },
94
    );
95

96
    if (taskError) {
97
      throw new Error(`Failed to get task ${taskId}: ${JSON.stringify(taskError)}`);
98
    }
99
    const task = taskData.ocs?.data?.task;
100
    const status = task.status;
101

102
    if (status === "STATUS_SUCCESSFUL") {
103
      const output = task.output;
104
      if (output && typeof output.output === "string") {
105
        return { analysisText: output.output, taskId };
106
      }
107
      return { analysisText: output, taskId };
108
    }
109

110
    if (status === "STATUS_FAILED" || status === "STATUS_CANCELLED") {
111
      const msg = JSON.stringify(task);
112
      throw new Error(`Image analysis task failed: ${msg}`);
113
    }
114
    if (!["STATUS_SCHEDULED", "STATUS_RUNNING"].includes(status)) {
115
      const msg = JSON.stringify(task);
116
      throw new Error(`Image analysis task failed with unknown status: ${msg}`);
117
    }
118
    await new Promise((r) => setTimeout(r, interval_ms));
119
  }
120

121
  throw new Error(
122
    `Image analysis task did not complete within ${timeout_ms}ms (taskId: ${taskId})`,
123
  );
124
}
125

126