Need a little help using DT 4.1 AI Applescript building

Always a pleasure to see the js version!

Let us know if you get any useful news.

1 Like

In the meantime, Claude is working, just got an API (Sonnet, $5 + taxes)

Just for fun, folks - I do intend to be playing with it and looking at what the model comes up with, knowing fully that it might be %6**)) !!!

You would obviously know what I told Claude to do :slight_smile:

1 Like

yep, all ok!

1 Like

Making it just a bit more complex. AI prompt was “Count the number of “.avif” records”

Well, not too bad for simple stuff that I can look at and debug if needed.

Just for the fun of it: Could you generate a JavaScript script with the same prompt? I’d like to see how that looks.

1 Like

And while it’s easy to criticize the results as elementary…

  1. The script in this case is not far off from functional: name should more safely be filename.
  2. @cgrunenberg worked to have the AI do better and know some about typical DT scripting errors. So not only do you get useful handlers built-in, the AI script is more “smartly coded” than what you’d get from generic AI requests.

At least this can give someone new to scripting a useful starting point.

1 Like

Claude 4 Sonnet Prompt: count the pdf files in the selection

(() => {
    const app = Application("DEVONthink");
    app.includeStandardAdditions = true;

    let records = app.selectedRecords();
    let pdfCount = 0;
    
    records.forEach(record => {
        if (record.recordType() === "PDF document") {
            pdfCount++;
        }
    });
    
    app.displayDialog(`Number of PDF files in selection: ${pdfCount}`);
})();

will do!

(() => {
const app = Application(“DEVONthink”);
app.includeStandardAdditions = true;

let records = app.selectedRecords();
let avifCount = 0;

records.forEach(r => {
	if (r.name().toLowerCase().endsWith('.avif')) {
		avifCount++;
	}
});

app.displayAlert(`Found ${avifCount} AVIF record${avifCount !== 1 ? 's' : ''}`);

})();

And it found the 3 .avif

hm, sorry bout the ugly misformatting above

Indeed!

Fixed.

1 Like

Merci!

I tried something reasonably harder, which was”

Use bash regex to replace “(dddd)” with “----”

Note: I am quite sure my regex is wrong :slight_smile:

It built this:

Not too bad, it knew ho to write the shell script, which of course didn’t work, certainly due to me.

Because, it understood that I meant - the content -

And of course I hadn’t told it to operate on the record names.

I changed the script to this, with some cleanup:

And that didn’t work either, and I’m sure it’s just me writing bad regex patterns

And logically, YMMV based on the model…

Qwen3 Coder

(() => {
	const app = Application("DEVONthink");
	app.includeStandardAdditions = true;

	let records = app.selectedRecords();
	let pdfCount = 0;

	records.forEach(r => {
		if (r.recordType() === "PDF document") {
			pdfCount++;
		}
	});

	console.log(`Number of PDF files in selection: ${pdfCount}`);
	return pdfCount;
})();

Grok Code Fast 1

(() => {
	'use strict';
	const app = Application("DEVONthink");
	app.includeStandardAdditions = true;

	try {
		let records = app.selectedRecords();
		if (!records || records.length === 0) {
			console.log("No records selected.");
			return 0;
		}

		let pdfCount = 0;
		records.forEach(r => {
			if (r.recordType() === "PDF document") {
				pdfCount++;
			}
		});

		console.log(`Number of PDF files in selection: ${pdfCount}`);
		return pdfCount;
	} catch (error) {
		console.error(`Error counting PDF files: ${error.message}`);
		return 0;
	}
})();

Devstral Medium

// Get the current application
const app = Application('DEVONthink 3');

// Get the current selection
const selection = app.selection();

// Initialize a counter for PDF files
let pdfCount = 0;

// Iterate through the selection
selection.forEach(record => {
  // Check if the record is a PDF document
  if (record.recordType() === 'PDF document') {
    pdfCount++;
  }
});

// Log the count of PDF files
console.log(`Number of PDF files in selection: ${pdfCount}`);

Noting the improved commenting from Devstral

Gemini Flash 2.5

(() => {
    const app = Application("DEVONthink");
    app.includeStandardAdditions = true;

    try {
        const selectedRecords = app.selection();

        if (!selectedRecords || selectedRecords.length === 0) {
            app.displayAlert("No Selection", "Please select some records in DEVONthink.");
            return 0;
        }

        let pdfCount = 0;
        for (let i = 0; i < selectedRecords.length; i++) {
            const currentRecord = selectedRecords[i];
            // Check if the record type is 'PDF document'
            if (currentRecord.recordType() === app.dataTypes.PDFDocument) {
                pdfCount++;
            }
        }

        app.displayAlert("PDF Count", `There are ${pdfCount} PDF documents in the current selection.`);
        return pdfCount;

    } catch (error) {
        // Log the error to DEVONthink's log window and display an alert
        const errorMessage = `Error counting PDFs: ${error.message || error}`;
        app.logMessage(errorMessage);
        app.displayAlert("Script Error", errorMessage);
        return -1; // Indicate an error
    }
})();

The award for trying too hard IMHO :stuck_out_tongue:

And singling out this model, here is the same request made for AppleScript…

tell application id "DNtp"
	try
		set theRecords to selected records
		set pdfCount to 0
		
		if (count of theRecords) is 0 then
			display dialog "No records are currently selected." with title "DEVONthink Automation"
			return
		end if
		
		repeat with theRecord in theRecords
			if the record type of theRecord is PDF document then
				set pdfCount to pdfCount + 1
			end if
		end repeat
		
		display dialog "Found " & pdfCount & " PDF file(s) in the selection." with title "DEVONthink PDF Count"
		
	on error errMsg number errNum
		if errNum = -1728 then -- Can't get selected records (e.g., no selection or no open database)
			display dialog "DEVONthink is running, but no records are selected or no database is open." with title "DEVONthink Automation Error" buttons {"OK"} default button 1 with icon caution
		else if errNum = -10000 then -- Application not running
			display dialog "DEVONthink is not running." with title "DEVONthink Automation Error" buttons {"OK"} default button 1 with icon caution
		else
			display dialog "An error occurred: " & errMsg & " (Error number: " & errNum & ")" with title "DEVONthink Automation Error" buttons {"OK"} default button 1 with icon caution
		end if
	end try
end tell

Again, trying too hard.


Criss would have to comment on any more specific tweaking he may have (or have not) made for e.g., Claude, but the most succinct and immediately understandable are from Claude and GPT.

1 Like

Very interesting Jim, thanks!

P.S. fascinating!

2 Likes

Thanks. That’s what I expected – CS 101

(() => {
  const app = Application(“DEVONthink”);
  app.includeStandardAdditions = true;
  const avifCount = app.selectedRecords()
    .filter(r => r.filename().toLowerCase().endsWith('.avif')).length;
  app.displayAlert(`Found ${avifCount} AVIF record${avifCount !== 1 ? 's' : ''}`)
})

IMO, the AI-generated code is good for beginners to get an idea of JS (and perhaps AppleScript, too). But in both cases, a seasoned programmer would write different code. In AS, something like

set avifCount to count of (selected records whose filename ends with ".avif")

The repeat and forEach approach are kind of “brute force”, imo.

2 Likes

That is really cringe-worthy. And this line …
if (currentRecord.recordType() === app.dataTypes.PDFDocument) {
?
The right-hand side is undefined and the left-hand side is a string. So this condition should always be false. And then this useless try … catch block which will never tell you where the problem happened.